1. /*
  2. * @(#)DataOutputStream.java 1.29 01/11/29
  3. *
  4. * Copyright 2002 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 input 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.29, 11/29/01
  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. OutputStream out = this.out;
  136. out.write((v >>> 8) & 0xFF);
  137. out.write((v >>> 0) & 0xFF);
  138. incCount(2);
  139. }
  140. /**
  141. * Writes a <code>char</code> to the underlying output stream as a
  142. * 2-byte value, high byte first. If no exception is thrown, the
  143. * counter <code>written</code> is incremented by <code>2</code>.
  144. *
  145. * @param v a <code>char</code> value to be written.
  146. * @exception IOException if an I/O error occurs.
  147. * @see java.io.FilterOutputStream#out
  148. */
  149. public final void writeChar(int v) throws IOException {
  150. OutputStream out = this.out;
  151. out.write((v >>> 8) & 0xFF);
  152. out.write((v >>> 0) & 0xFF);
  153. incCount(2);
  154. }
  155. /**
  156. * Writes an <code>int</code> to the underlying output stream as four
  157. * bytes, high byte first. If no exception is thrown, the counter
  158. * <code>written</code> is incremented by <code>4</code>.
  159. *
  160. * @param v an <code>int</code> to be written.
  161. * @exception IOException if an I/O error occurs.
  162. * @see java.io.FilterOutputStream#out
  163. */
  164. public final void writeInt(int v) throws IOException {
  165. OutputStream out = this.out;
  166. out.write((v >>> 24) & 0xFF);
  167. out.write((v >>> 16) & 0xFF);
  168. out.write((v >>> 8) & 0xFF);
  169. out.write((v >>> 0) & 0xFF);
  170. incCount(4);
  171. }
  172. /**
  173. * Writes a <code>long</code> to the underlying output stream as eight
  174. * bytes, high byte first. In no exception is thrown, the counter
  175. * <code>written</code> is incremented by <code>8</code>.
  176. *
  177. * @param v a <code>long</code> to be written.
  178. * @exception IOException if an I/O error occurs.
  179. * @see java.io.FilterOutputStream#out
  180. */
  181. public final void writeLong(long v) throws IOException {
  182. OutputStream out = this.out;
  183. out.write((int)(v >>> 56) & 0xFF);
  184. out.write((int)(v >>> 48) & 0xFF);
  185. out.write((int)(v >>> 40) & 0xFF);
  186. out.write((int)(v >>> 32) & 0xFF);
  187. out.write((int)(v >>> 24) & 0xFF);
  188. out.write((int)(v >>> 16) & 0xFF);
  189. out.write((int)(v >>> 8) & 0xFF);
  190. out.write((int)(v >>> 0) & 0xFF);
  191. incCount(8);
  192. }
  193. /**
  194. * Converts the float argument to an <code>int</code> using the
  195. * <code>floatToIntBits</code> method in class <code>Float</code>,
  196. * and then writes that <code>int</code> value to the underlying
  197. * output stream as a 4-byte quantity, high byte first. If no
  198. * exception is thrown, the counter <code>written</code> is
  199. * incremented by <code>4</code>.
  200. *
  201. * @param v a <code>float</code> value to be written.
  202. * @exception IOException if an I/O error occurs.
  203. * @see java.io.FilterOutputStream#out
  204. * @see java.lang.Float#floatToIntBits(float)
  205. */
  206. public final void writeFloat(float v) throws IOException {
  207. writeInt(Float.floatToIntBits(v));
  208. }
  209. /**
  210. * Converts the double argument to a <code>long</code> using the
  211. * <code>doubleToLongBits</code> method in class <code>Double</code>,
  212. * and then writes that <code>long</code> value to the underlying
  213. * output stream as an 8-byte quantity, high byte first. If no
  214. * exception is thrown, the counter <code>written</code> is
  215. * incremented by <code>8</code>.
  216. *
  217. * @param v a <code>double</code> value to be written.
  218. * @exception IOException if an I/O error occurs.
  219. * @see java.io.FilterOutputStream#out
  220. * @see java.lang.Double#doubleToLongBits(double)
  221. */
  222. public final void writeDouble(double v) throws IOException {
  223. writeLong(Double.doubleToLongBits(v));
  224. }
  225. /**
  226. * Writes out the string to the underlying output stream as a
  227. * sequence of bytes. Each character in the string is written out, in
  228. * sequence, by discarding its high eight bits. If no exception is
  229. * thrown, the counter <code>written</code> is incremented by the
  230. * length of <code>s</code>.
  231. *
  232. * @param s a string of bytes to be written.
  233. * @exception IOException if an I/O error occurs.
  234. * @see java.io.FilterOutputStream#out
  235. */
  236. public final void writeBytes(String s) throws IOException {
  237. OutputStream out = this.out;
  238. int len = s.length();
  239. for (int i = 0 ; i < len ; i++) {
  240. out.write((byte)s.charAt(i));
  241. }
  242. incCount(len);
  243. }
  244. /**
  245. * Writes a string to the underlying output stream as a sequence of
  246. * characters. Each character is written to the data output stream as
  247. * if by the <code>writeChar</code> method. If no exception is
  248. * thrown, the counter <code>written</code> is incremented by twice
  249. * the length of <code>s</code>.
  250. *
  251. * @param s a <code>String</code> value to be written.
  252. * @exception IOException if an I/O error occurs.
  253. * @see java.io.DataOutputStream#writeChar(int)
  254. * @see java.io.FilterOutputStream#out
  255. */
  256. public final void writeChars(String s) throws IOException {
  257. OutputStream out = this.out;
  258. int len = s.length();
  259. for (int i = 0 ; i < len ; i++) {
  260. int v = s.charAt(i);
  261. out.write((v >>> 8) & 0xFF);
  262. out.write((v >>> 0) & 0xFF);
  263. }
  264. incCount(len * 2);
  265. }
  266. /**
  267. * Writes a string to the underlying output stream using UTF-8
  268. * encoding in a machine-independent manner.
  269. * <p>
  270. * First, two bytes are written to the output stream as if by the
  271. * <code>writeShort</code> method giving the number of bytes to
  272. * follow. This value is the number of bytes actually written out,
  273. * not the length of the string. Following the length, each character
  274. * of the string is output, in sequence, using the UTF-8 encoding
  275. * for the character. If no exception is thrown, the counter
  276. * <code>written</code> is incremented by the total number of
  277. * bytes written to the output stream. This will be at least two
  278. * plus the length of <code>str</code>, and at most two plus
  279. * thrice the length of <code>str</code>.
  280. *
  281. * @param str a string to be written.
  282. * @exception IOException if an I/O error occurs.
  283. */
  284. public final void writeUTF(String str) throws IOException {
  285. OutputStream out = this.out;
  286. int strlen = str.length();
  287. int utflen = 0;
  288. for (int i = 0 ; i < strlen ; i++) {
  289. int c = str.charAt(i);
  290. if ((c >= 0x0001) && (c <= 0x007F)) {
  291. utflen++;
  292. } else if (c > 0x07FF) {
  293. utflen += 3;
  294. } else {
  295. utflen += 2;
  296. }
  297. }
  298. if (utflen > 65535)
  299. throw new UTFDataFormatException();
  300. out.write((utflen >>> 8) & 0xFF);
  301. out.write((utflen >>> 0) & 0xFF);
  302. for (int i = 0 ; i < strlen ; i++) {
  303. int c = str.charAt(i);
  304. if ((c >= 0x0001) && (c <= 0x007F)) {
  305. out.write(c);
  306. } else if (c > 0x07FF) {
  307. out.write(0xE0 | ((c >> 12) & 0x0F));
  308. out.write(0x80 | ((c >> 6) & 0x3F));
  309. out.write(0x80 | ((c >> 0) & 0x3F));
  310. incCount(2);
  311. } else {
  312. out.write(0xC0 | ((c >> 6) & 0x1F));
  313. out.write(0x80 | ((c >> 0) & 0x3F));
  314. incCount(1);
  315. }
  316. }
  317. incCount(strlen + 2);
  318. }
  319. /**
  320. * Returns the current value of the counter <code>written</code>,
  321. * the number of bytes written to this data output stream so far.
  322. * If the counter overflows, it will be wrapped to Integer.MAX_VALUE.
  323. *
  324. * @return the value of the <code>written</code> field.
  325. * @see java.io.DataOutputStream#written
  326. */
  327. public final int size() {
  328. return written;
  329. }
  330. }