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