GNU Classpath (0.20) | |
Frames | No Frames |
1: /* DataOutputStream.java -- Writes primitive Java datatypes to streams 2: Copyright (C) 1998, 2001, 2003, 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package java.io; 40: 41: /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3 42: * "The Java Language Specification", ISBN 0-201-63451-1 43: * Status: Complete to version 1.1. 44: */ 45: 46: /** 47: * This class provides a mechanism for writing primitive Java datatypes 48: * to an <code>OutputStream</code> in a portable way. Data written to 49: * a stream using this class can be read back in using the 50: * <code>DataInputStream</code> class on any platform. 51: * 52: * @see DataInputStream 53: * 54: * @author Aaron M. Renn (arenn@urbanophile.com) 55: * @author Tom Tromey (tromey@cygnus.com) 56: */ 57: public class DataOutputStream extends FilterOutputStream implements DataOutput 58: { 59: /** 60: * This is the total number of bytes that have been written to the 61: * stream by this object instance. 62: */ 63: protected int written; 64: 65: /** 66: * This method initializes an instance of <code>DataOutputStream</code> to 67: * write its data to the specified underlying <code>OutputStream</code> 68: * 69: * @param out The subordinate <code>OutputStream</code> to which this 70: * object will write 71: */ 72: public DataOutputStream (OutputStream out) 73: { 74: super (out); 75: written = 0; 76: } 77: 78: /** 79: * This method flushes any unwritten bytes to the underlying stream. 80: * 81: * @exception IOException If an error occurs. 82: */ 83: public void flush () throws IOException 84: { 85: out.flush(); 86: } 87: 88: /** 89: * This method returns the total number of bytes that have been written to 90: * the underlying output stream so far. This is the value of the 91: * <code>written</code> instance variable 92: * 93: * @return The number of bytes written to the stream. 94: */ 95: public final int size () 96: { 97: return written; 98: } 99: 100: /** 101: * This method writes the specified byte (passed as an <code>int</code>) 102: * to the underlying output stream. 103: * 104: * @param value The <code>byte</code> to write, passed as an <code>int</code>. 105: * 106: * @exception IOException If an error occurs. 107: */ 108: public synchronized void write (int value) throws IOException 109: { 110: out.write (value); 111: ++written; 112: } 113: 114: /** 115: * This method writes <code>len</code> bytes from the specified byte array 116: * <code>buf</code> starting at position <code>offset</code> into the 117: * buffer to the underlying output stream. 118: * 119: * @param buf The byte array to write from. 120: * @param offset The index into the byte array to start writing from. 121: * @param len The number of bytes to write. 122: * 123: * @exception IOException If an error occurs. 124: */ 125: public synchronized void write (byte[] buf, int offset, int len) 126: throws IOException 127: { 128: out.write(buf, offset, len); 129: written += len; 130: } 131: 132: /** 133: * This method writes a Java boolean value to an output stream. If 134: * <code>value</code> is <code>true</code>, a byte with the value of 135: * 1 will be written, otherwise a byte with the value of 0 will be 136: * written. 137: * 138: * The value written can be read using the <code>readBoolean</code> 139: * method in <code>DataInput</code>. 140: * 141: * @param value The <code>boolean</code> value to write to the stream 142: * 143: * @exception IOException If an error occurs 144: * 145: * @see DataInput#readBoolean 146: */ 147: public final void writeBoolean (boolean value) throws IOException 148: { 149: write (value ? 1 : 0); 150: } 151: 152: /** 153: * This method writes a Java byte value to an output stream. The 154: * byte to be written will be in the lowest 8 bits of the 155: * <code>int</code> value passed. 156: * 157: * The value written can be read using the <code>readByte</code> or 158: * <code>readUnsignedByte</code> methods in <code>DataInput</code>. 159: * 160: * @param value The <code>byte</code> to write to the stream, passed as 161: * the low eight bits of an <code>int</code>. 162: * 163: * @exception IOException If an error occurs 164: * 165: * @see DataInput#readByte 166: * @see DataInput#readUnsignedByte 167: */ 168: public final void writeByte (int value) throws IOException 169: { 170: write (value & 0xff); 171: } 172: 173: /** 174: * This method writes a Java short value to an output stream. The 175: * char to be written will be in the lowest 16 bits of the <code>int</code> 176: * value passed. These bytes will be written "big endian". That is, 177: * with the high byte written first in the following manner: 178: * <p> 179: * <code>byte0 = (byte)((value & 0xFF00) >> 8);<br> 180: * byte1 = (byte)(value & 0x00FF);</code> 181: * <p> 182: * 183: * The value written can be read using the <code>readShort</code> and 184: * <code>readUnsignedShort</code> methods in <code>DataInput</code>. 185: * 186: * @param value The <code>short</code> value to write to the stream, 187: * passed as an <code>int</code>. 188: * 189: * @exception IOException If an error occurs 190: * 191: * @see DataInput#readShort 192: * @see DataInput#readUnsignedShort 193: */ 194: public final synchronized void writeShort (int value) throws IOException 195: { 196: write ((byte) (0xff & (value >> 8))); 197: write ((byte) (0xff & value)); 198: } 199: 200: /** 201: * This method writes a Java char value to an output stream. The 202: * char to be written will be in the lowest 16 bits of the <code>int</code> 203: * value passed. These bytes will be written "big endian". That is, 204: * with the high byte written first in the following manner: 205: * <p> 206: * <code>byte0 = (byte)((value & 0xFF00) >> 8);<br> 207: * byte1 = (byte)(value & 0x00FF);</code> 208: * <p> 209: * 210: * The value written can be read using the <code>readChar</code> 211: * method in <code>DataInput</code>. 212: * 213: * @param value The <code>char</code> value to write, 214: * passed as an <code>int</code>. 215: * 216: * @exception IOException If an error occurs 217: * 218: * @see DataInput#readChar 219: */ 220: public final synchronized void writeChar (int value) throws IOException 221: { 222: write ((byte) (0xff & (value >> 8))); 223: write ((byte) (0xff & value)); 224: } 225: 226: /** 227: * This method writes a Java int value to an output stream. The 4 bytes 228: * of the passed value will be written "big endian". That is, with 229: * the high byte written first in the following manner: 230: * <p> 231: * <code>byte0 = (byte)((value & 0xFF000000) >> 24);<br> 232: * byte1 = (byte)((value & 0x00FF0000) >> 16);<br> 233: * byte2 = (byte)((value & 0x0000FF00) >> 8);<br> 234: * byte3 = (byte)(value & 0x000000FF);</code> 235: * <p> 236: * 237: * The value written can be read using the <code>readInt</code> 238: * method in <code>DataInput</code>. 239: * 240: * @param value The <code>int</code> value to write to the stream 241: * 242: * @exception IOException If an error occurs 243: * 244: * @see DataInput#readInt 245: */ 246: public final synchronized void writeInt (int value) throws IOException 247: { 248: write ((byte) (0xff & (value >> 24))); 249: write ((byte) (0xff & (value >> 16))); 250: write ((byte) (0xff & (value >> 8))); 251: write ((byte) (0xff & value)); 252: } 253: 254: /** 255: * This method writes a Java long value to an output stream. The 8 bytes 256: * of the passed value will be written "big endian". That is, with 257: * the high byte written first in the following manner: 258: * <p> 259: * <code>byte0 = (byte)((value & 0xFF00000000000000L) >> 56);<br> 260: * byte1 = (byte)((value & 0x00FF000000000000L) >> 48);<br> 261: * byte2 = (byte)((value & 0x0000FF0000000000L) >> 40);<br> 262: * byte3 = (byte)((value & 0x000000FF00000000L) >> 32);<br> 263: * byte4 = (byte)((value & 0x00000000FF000000L) >> 24);<br> 264: * byte5 = (byte)((value & 0x0000000000FF0000L) >> 16);<br> 265: * byte6 = (byte)((value & 0x000000000000FF00L) >> 8);<br> 266: * byte7 = (byte)(value & 0x00000000000000FFL);</code> 267: * <p> 268: * 269: * The value written can be read using the <code>readLong</code> 270: * method in <code>DataInput</code>. 271: * 272: * @param value The <code>long</code> value to write to the stream 273: * 274: * @exception IOException If an error occurs 275: * 276: * @see DataInput#readLong 277: */ 278: public final synchronized void writeLong (long value) throws IOException 279: { 280: write ((byte) (0xff & (value >> 56))); 281: write ((byte) (0xff & (value>> 48))); 282: write ((byte) (0xff & (value>> 40))); 283: write ((byte) (0xff & (value>> 32))); 284: write ((byte) (0xff & (value>> 24))); 285: write ((byte) (0xff & (value>> 16))); 286: write ((byte) (0xff & (value>> 8))); 287: write ((byte) (0xff & value)); 288: } 289: 290: /** 291: * This method writes a Java <code>float</code> value to the stream. This 292: * value is written by first calling the method 293: * <code>Float.floatToIntBits</code> 294: * to retrieve an <code>int</code> representing the floating point number, 295: * then writing this <code>int</code> value to the stream exactly the same 296: * as the <code>writeInt()</code> method does. 297: * 298: * The value written can be read using the <code>readFloat</code> 299: * method in <code>DataInput</code>. 300: * 301: * @param value The <code>float</code> value to write to the stream 302: * 303: * @exception IOException If an error occurs 304: * 305: * @see #writeInt(int) 306: * @see DataInput#readFloat 307: * @see Float#floatToIntBits 308: */ 309: public final void writeFloat (float value) throws IOException 310: { 311: writeInt (Float.floatToIntBits (value)); 312: } 313: 314: /** 315: * This method writes a Java <code>double</code> value to the stream. This 316: * value is written by first calling the method 317: * <code>Double.doubleToLongBits</code> 318: * to retrieve an <code>long</code> representing the floating point number, 319: * then writing this <code>long</code> value to the stream exactly the same 320: * as the <code>writeLong()</code> method does. 321: * 322: * The value written can be read using the <code>readDouble</code> 323: * method in <code>DataInput</code>. 324: * 325: * @param value The <code>double</code> value to write to the stream 326: * 327: * @exception IOException If an error occurs 328: * 329: * @see #writeLong(long) 330: * @see DataInput#readDouble 331: * @see Double#doubleToLongBits 332: */ 333: public final void writeDouble (double value) throws IOException 334: { 335: writeLong (Double.doubleToLongBits (value)); 336: } 337: 338: /** 339: * This method writes all the bytes in a <code>String</code> out to the 340: * stream. One byte is written for each character in the 341: * <code>String</code>. 342: * The high eight bits of each character are discarded, thus this 343: * method is inappropriate for completely representing Unicode characters. 344: * 345: * @param value The <code>String</code> to write to the stream 346: * 347: * @exception IOException If an error occurs 348: */ 349: public final void writeBytes (String value) throws IOException 350: { 351: int len = value.length(); 352: for (int i = 0; i < len; ++i) 353: writeByte (value.charAt(i)); 354: } 355: 356: /** 357: * This method writes all the characters of a <code>String</code> to an 358: * output stream as an array of <code>char</code>'s. Each character 359: * is written using the method specified in the <code>writeChar</code> 360: * method. 361: * 362: * @param value The <code>String</code> to write to the stream 363: * 364: * @exception IOException If an error occurs 365: * 366: * @see #writeChar(char) 367: */ 368: public final void writeChars (String value) throws IOException 369: { 370: int len = value.length(); 371: for (int i = 0; i < len; ++i) 372: writeChar (value.charAt(i)); 373: } 374: 375: /** 376: * This method writes a Java <code>String</code> to the stream in a modified 377: * UTF-8 format. First, two bytes are written to the stream indicating the 378: * number of bytes to follow. Note that this is the number of bytes in the 379: * encoded <code>String</code> not the <code>String</code> length. Next 380: * come the encoded characters. Each character in the <code>String</code> 381: * is encoded as either one, two or three bytes. For characters in the 382: * range of <code>\u0001</code> to <\u007F>, one byte is used. The character 383: * value goes into bits 0-7 and bit eight is 0. For characters in the range 384: * of <code>\u0080</code> to <code>\u007FF</code>, two bytes are used. Bits 385: * 6-10 of the character value are encoded bits 0-4 of the first byte, with 386: * the high bytes having a value of "110". Bits 0-5 of the character value 387: * are stored in bits 0-5 of the second byte, with the high bits set to 388: * "10". This type of encoding is also done for the null character 389: * <code>\u0000</code>. This eliminates any C style NUL character values 390: * in the output. All remaining characters are stored as three bytes. 391: * Bits 12-15 of the character value are stored in bits 0-3 of the first 392: * byte. The high bits of the first bytes are set to "1110". Bits 6-11 393: * of the character value are stored in bits 0-5 of the second byte. The 394: * high bits of the second byte are set to "10". And bits 0-5 of the 395: * character value are stored in bits 0-5 of byte three, with the high bits 396: * of that byte set to "10". 397: * 398: * The value written can be read using the <code>readUTF</code> 399: * method in <code>DataInput</code>. 400: * 401: * @param value The <code>String</code> to write to the output in UTF format 402: * 403: * @exception IOException If an error occurs 404: * 405: * @see DataInput#readUTF 406: */ 407: public final synchronized void writeUTF(String value) throws IOException 408: { 409: int len = value.length(); 410: int sum = 0; 411: 412: for (int i = 0; i < len && sum <= 65535; ++i) 413: { 414: char c = value.charAt(i); 415: if (c >= '\u0001' && c <= '\u007f') 416: sum += 1; 417: else if (c == '\u0000' || (c >= '\u0080' && c <= '\u07ff')) 418: sum += 2; 419: else 420: sum += 3; 421: } 422: 423: if (sum > 65535) 424: throw new UTFDataFormatException (); 425: 426: int pos = 0; 427: byte[] buf = new byte[sum]; 428: 429: for (int i = 0; i < len; ++i) 430: { 431: char c = value.charAt(i); 432: if (c >= '\u0001' && c <= '\u007f') 433: buf[pos++] = (byte) c; 434: else if (c == '\u0000' || (c >= '\u0080' && c <= '\u07ff')) 435: { 436: buf[pos++] = (byte) (0xc0 | (0x1f & (c >> 6))); 437: buf[pos++] = (byte) (0x80 | (0x3f & c)); 438: } 439: else 440: { 441: // JSL says the first byte should be or'd with 0xc0, but 442: // that is a typo. Unicode says 0xe0, and that is what is 443: // consistent with DataInputStream. 444: buf[pos++] = (byte) (0xe0 | (0x0f & (c >> 12))); 445: buf[pos++] = (byte) (0x80 | (0x3f & (c >> 6))); 446: buf[pos++] = (byte) (0x80 | (0x3f & c)); 447: } 448: } 449: 450: writeShort (sum); 451: write(buf, 0, sum); 452: } 453: 454: } // class DataOutputStream
GNU Classpath (0.20) |