1. /*
  2. * @(#)DataOutputStream.java 1.32 00/02/02
  3. *
  4. * Copyright 1994-2000 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. package java.io;
  11. /**
  12. * A data input stream lets an application write primitive Java data
  13. * types to an output stream in a portable way. An application can
  14. * then use a data input stream to read the data back in.
  15. *
  16. * @author unascribed
  17. * @version 1.32, 02/02/00
  18. * @see java.io.DataInputStream
  19. * @since JDK1.0
  20. */
  21. public
  22. class DataOutputStream extends FilterOutputStream implements DataOutput {
  23. /**
  24. * The number of bytes written to the data output stream so far.
  25. * If this counter overflows, it will be wrapped to Integer.MAX_VALUE.
  26. */
  27. protected int written;
  28. /**
  29. * Creates a new data output stream to write data to the specified
  30. * underlying output stream. The counter <code>written</code> is
  31. * set to zero.
  32. *
  33. * @param out the underlying output stream, to be saved for later
  34. * use.
  35. * @see java.io.FilterOutputStream#out
  36. */
  37. public DataOutputStream(OutputStream out) {
  38. super(out);
  39. }
  40. /**
  41. * Increases the written counter by the specified value
  42. * until it reaches Integer.MAX_VALUE.
  43. */
  44. private void incCount(int value) {
  45. int temp = written + value;
  46. if (temp < 0) {
  47. temp = Integer.MAX_VALUE;
  48. }
  49. written = temp;
  50. }
  51. /**
  52. * Writes the specified byte (the low eight bits of the argument
  53. * <code>b</code>) to the underlying output stream. If no exception
  54. * is thrown, the counter <code>written</code> is incremented by
  55. * <code>1</code>.
  56. * <p>
  57. * Implements the <code>write</code> method of <code>OutputStream</code>.
  58. *
  59. * @param b the <code>byte</code> to be written.
  60. * @exception IOException if an I/O error occurs.
  61. * @see java.io.FilterOutputStream#out
  62. */
  63. public synchronized void write(int b) throws IOException {
  64. out.write(b);
  65. incCount(1);
  66. }
  67. /**
  68. * Writes <code>len</code> bytes from the specified byte array
  69. * starting at offset <code>off</code> to the underlying output stream.
  70. * If no exception is thrown, the counter <code>written</code> is
  71. * incremented by <code>len</code>.
  72. *
  73. * @param b the data.
  74. * @param off the start offset in the data.
  75. * @param len the number of bytes to write.
  76. * @exception IOException if an I/O error occurs.
  77. * @see java.io.FilterOutputStream#out
  78. */
  79. public synchronized void write(byte b[], int off, int len)
  80. throws IOException
  81. {
  82. out.write(b, off, len);
  83. incCount(len);
  84. }
  85. /**
  86. * Flushes this data output stream. This forces any buffered output
  87. * bytes to be written out to the stream.
  88. * <p>
  89. * The <code>flush</code> method of <code>DataOuputStream</code>
  90. * calls the <code>flush</code> method of its underlying output stream.
  91. *
  92. * @exception IOException if an I/O error occurs.
  93. * @see java.io.FilterOutputStream#out
  94. * @see java.io.OutputStream#flush()
  95. */
  96. public void flush() throws IOException {
  97. out.flush();
  98. }
  99. /**
  100. * Writes a <code>boolean</code> to the underlying output stream as
  101. * a 1-byte value. The value <code>true</code> is written out as the
  102. * value <code>(byte)1</code> the value <code>false</code> is
  103. * written out as the value <code>(byte)0</code>. If no exception is
  104. * thrown, the counter <code>written</code> is incremented by
  105. * <code>1</code>.
  106. *
  107. * @param v a <code>boolean</code> value to be written.
  108. * @exception IOException if an I/O error occurs.
  109. * @see java.io.FilterOutputStream#out
  110. */
  111. public final void writeBoolean(boolean v) throws IOException {
  112. out.write(v ? 1 : 0);
  113. incCount(1);
  114. }
  115. /**
  116. * Writes out a <code>byte</code> to the underlying output stream as
  117. * a 1-byte value. If no exception is thrown, the counter
  118. * <code>written</code> is incremented by <code>1</code>.
  119. *
  120. * @param v a <code>byte</code> value to be written.
  121. * @exception IOException if an I/O error occurs.
  122. * @see java.io.FilterOutputStream#out
  123. */
  124. public final void writeByte(int v) throws IOException {
  125. out.write(v);
  126. incCount(1);
  127. }
  128. /**
  129. * Writes a <code>short</code> to the underlying output stream as two
  130. * bytes, high byte first. If no exception is thrown, the counter
  131. * <code>written</code> is incremented by <code>2</code>.
  132. *
  133. * @param v a <code>short</code> to be written.
  134. * @exception IOException if an I/O error occurs.
  135. * @see java.io.FilterOutputStream#out
  136. */
  137. public final void writeShort(int v) throws IOException {
  138. OutputStream out = this.out;
  139. out.write((v >>> 8) & 0xFF);
  140. out.write((v >>> 0) & 0xFF);
  141. incCount(2);
  142. }
  143. /**
  144. * Writes a <code>char</code> to the underlying output stream as a
  145. * 2-byte value, high byte first. If no exception is thrown, the
  146. * counter <code>written</code> is incremented by <code>2</code>.
  147. *
  148. * @param v a <code>char</code> value to be written.
  149. * @exception IOException if an I/O error occurs.
  150. * @see java.io.FilterOutputStream#out
  151. */
  152. public final void writeChar(int v) throws IOException {
  153. OutputStream out = this.out;
  154. out.write((v >>> 8) & 0xFF);
  155. out.write((v >>> 0) & 0xFF);
  156. incCount(2);
  157. }
  158. /**
  159. * Writes an <code>int</code> to the underlying output stream as four
  160. * bytes, high byte first. If no exception is thrown, the counter
  161. * <code>written</code> is incremented by <code>4</code>.
  162. *
  163. * @param v an <code>int</code> to be written.
  164. * @exception IOException if an I/O error occurs.
  165. * @see java.io.FilterOutputStream#out
  166. */
  167. public final void writeInt(int v) throws IOException {
  168. OutputStream out = this.out;
  169. out.write((v >>> 24) & 0xFF);
  170. out.write((v >>> 16) & 0xFF);
  171. out.write((v >>> 8) & 0xFF);
  172. out.write((v >>> 0) & 0xFF);
  173. incCount(4);
  174. }
  175. /**
  176. * Writes a <code>long</code> to the underlying output stream as eight
  177. * bytes, high byte first. In no exception is thrown, the counter
  178. * <code>written</code> is incremented by <code>8</code>.
  179. *
  180. * @param v a <code>long</code> to be written.
  181. * @exception IOException if an I/O error occurs.
  182. * @see java.io.FilterOutputStream#out
  183. */
  184. public final void writeLong(long v) throws IOException {
  185. OutputStream out = this.out;
  186. out.write((int)(v >>> 56) & 0xFF);
  187. out.write((int)(v >>> 48) & 0xFF);
  188. out.write((int)(v >>> 40) & 0xFF);
  189. out.write((int)(v >>> 32) & 0xFF);
  190. out.write((int)(v >>> 24) & 0xFF);
  191. out.write((int)(v >>> 16) & 0xFF);
  192. out.write((int)(v >>> 8) & 0xFF);
  193. out.write((int)(v >>> 0) & 0xFF);
  194. incCount(8);
  195. }
  196. /**
  197. * Converts the float argument to an <code>int</code> using the
  198. * <code>floatToIntBits</code> method in class <code>Float</code>,
  199. * and then writes that <code>int</code> value to the underlying
  200. * output stream as a 4-byte quantity, high byte first. If no
  201. * exception is thrown, the counter <code>written</code> is
  202. * incremented by <code>4</code>.
  203. *
  204. * @param v a <code>float</code> value to be written.
  205. * @exception IOException if an I/O error occurs.
  206. * @see java.io.FilterOutputStream#out
  207. * @see java.lang.Float#floatToIntBits(float)
  208. */
  209. public final void writeFloat(float v) throws IOException {
  210. writeInt(Float.floatToIntBits(v));
  211. }
  212. /**
  213. * Converts the double argument to a <code>long</code> using the
  214. * <code>doubleToLongBits</code> method in class <code>Double</code>,
  215. * and then writes that <code>long</code> value to the underlying
  216. * output stream as an 8-byte quantity, high byte first. If no
  217. * exception is thrown, the counter <code>written</code> is
  218. * incremented by <code>8</code>.
  219. *
  220. * @param v a <code>double</code> value to be written.
  221. * @exception IOException if an I/O error occurs.
  222. * @see java.io.FilterOutputStream#out
  223. * @see java.lang.Double#doubleToLongBits(double)
  224. */
  225. public final void writeDouble(double v) throws IOException {
  226. writeLong(Double.doubleToLongBits(v));
  227. }
  228. /**
  229. * Writes out the string to the underlying output stream as a
  230. * sequence of bytes. Each character in the string is written out, in
  231. * sequence, by discarding its high eight bits. If no exception is
  232. * thrown, the counter <code>written</code> is incremented by the
  233. * length of <code>s</code>.
  234. *
  235. * @param s a string of bytes to be written.
  236. * @exception IOException if an I/O error occurs.
  237. * @see java.io.FilterOutputStream#out
  238. */
  239. public final void writeBytes(String s) throws IOException {
  240. OutputStream out = this.out;
  241. int len = s.length();
  242. for (int i = 0 ; i < len ; i++) {
  243. out.write((byte)s.charAt(i));
  244. }
  245. incCount(len);
  246. }
  247. /**
  248. * Writes a string to the underlying output stream as a sequence of
  249. * characters. Each character is written to the data output stream as
  250. * if by the <code>writeChar</code> method. If no exception is
  251. * thrown, the counter <code>written</code> is incremented by twice
  252. * the length of <code>s</code>.
  253. *
  254. * @param s a <code>String</code> value to be written.
  255. * @exception IOException if an I/O error occurs.
  256. * @see java.io.DataOutputStream#writeChar(int)
  257. * @see java.io.FilterOutputStream#out
  258. */
  259. public final void writeChars(String s) throws IOException {
  260. OutputStream out = this.out;
  261. int len = s.length();
  262. for (int i = 0 ; i < len ; i++) {
  263. int v = s.charAt(i);
  264. out.write((v >>> 8) & 0xFF);
  265. out.write((v >>> 0) & 0xFF);
  266. }
  267. incCount(len * 2);
  268. }
  269. /**
  270. * Writes a string to the underlying output stream using UTF-8
  271. * encoding in a machine-independent manner.
  272. * <p>
  273. * First, two bytes are written to the output stream as if by the
  274. * <code>writeShort</code> method giving the number of bytes to
  275. * follow. This value is the number of bytes actually written out,
  276. * not the length of the string. Following the length, each character
  277. * of the string is output, in sequence, using the UTF-8 encoding
  278. * for the character. If no exception is thrown, the counter
  279. * <code>written</code> is incremented by the total number of
  280. * bytes written to the output stream. This will be at least two
  281. * plus the length of <code>str</code>, and at most two plus
  282. * thrice the length of <code>str</code>.
  283. *
  284. * @param str a string to be written.
  285. * @exception IOException if an I/O error occurs.
  286. */
  287. public final void writeUTF(String str) throws IOException {
  288. writeUTF(str, this);
  289. }
  290. /**
  291. * Writes a string to the specified DataOutput using UTF-8 encoding in a
  292. * machine-independent manner.
  293. * <p>
  294. * First, two bytes are written to out as if by the <code>writeShort</code>
  295. * method giving the number of bytes to follow. This value is the number of
  296. * bytes actually written out, not the length of the string. Following the
  297. * length, each character of the string is output, in sequence, using the
  298. * UTF-8 encoding for the character. If no exception is thrown, the
  299. * counter <code>written</code> is incremented by the total number of
  300. * bytes written to the output stream. This will be at least two
  301. * plus the length of <code>str</code>, and at most two plus
  302. * thrice the length of <code>str</code>.
  303. *
  304. * @param str a string to be written.
  305. * @param out destination to write to
  306. * @return The number of bytes written out.
  307. * @exception IOException if an I/O error occurs.
  308. */
  309. static int writeUTF(String str, DataOutput out) throws IOException {
  310. int strlen = str.length();
  311. int utflen = 0;
  312. char[] charr = new char[strlen];
  313. int c, count = 0;
  314. str.getChars(0, strlen, charr, 0);
  315. for (int i = 0; i < strlen; i++) {
  316. c = charr[i];
  317. if ((c >= 0x0001) && (c <= 0x007F)) {
  318. utflen++;
  319. } else if (c > 0x07FF) {
  320. utflen += 3;
  321. } else {
  322. utflen += 2;
  323. }
  324. }
  325. if (utflen > 65535)
  326. throw new UTFDataFormatException();
  327. byte[] bytearr = new byte[utflen+2];
  328. bytearr[count++] = (byte) ((utflen >>> 8) & 0xFF);
  329. bytearr[count++] = (byte) ((utflen >>> 0) & 0xFF);
  330. for (int i = 0; i < strlen; i++) {
  331. c = charr[i];
  332. if ((c >= 0x0001) && (c <= 0x007F)) {
  333. bytearr[count++] = (byte) c;
  334. } else if (c > 0x07FF) {
  335. bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
  336. bytearr[count++] = (byte) (0x80 | ((c >> 6) & 0x3F));
  337. bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
  338. } else {
  339. bytearr[count++] = (byte) (0xC0 | ((c >> 6) & 0x1F));
  340. bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
  341. }
  342. }
  343. out.write(bytearr);
  344. return utflen + 2;
  345. }
  346. /**
  347. * Returns the current value of the counter <code>written</code>,
  348. * the number of bytes written to this data output stream so far.
  349. * If the counter overflows, it will be wrapped to Integer.MAX_VALUE.
  350. *
  351. * @return the value of the <code>written</code> field.
  352. * @see java.io.DataOutputStream#written
  353. */
  354. public final int size() {
  355. return written;
  356. }
  357. }