jaroslav@601: /* jaroslav@601: * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved. jaroslav@601: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jaroslav@601: * jaroslav@601: * This code is free software; you can redistribute it and/or modify it jaroslav@601: * under the terms of the GNU General Public License version 2 only, as jaroslav@601: * published by the Free Software Foundation. Oracle designates this jaroslav@601: * particular file as subject to the "Classpath" exception as provided jaroslav@601: * by Oracle in the LICENSE file that accompanied this code. jaroslav@601: * jaroslav@601: * This code is distributed in the hope that it will be useful, but WITHOUT jaroslav@601: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jaroslav@601: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jaroslav@601: * version 2 for more details (a copy is included in the LICENSE file that jaroslav@601: * accompanied this code). jaroslav@601: * jaroslav@601: * You should have received a copy of the GNU General Public License version jaroslav@601: * 2 along with this work; if not, write to the Free Software Foundation, jaroslav@601: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jaroslav@601: * jaroslav@601: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA jaroslav@601: * or visit www.oracle.com if you need additional information or have any jaroslav@601: * questions. jaroslav@601: */ jaroslav@601: jaroslav@601: package java.io; jaroslav@601: jaroslav@601: /** jaroslav@601: * A data output stream lets an application write primitive Java data jaroslav@601: * types to an output stream in a portable way. An application can jaroslav@601: * then use a data input stream to read the data back in. jaroslav@601: * jaroslav@601: * @author unascribed jaroslav@601: * @see java.io.DataInputStream jaroslav@601: * @since JDK1.0 jaroslav@601: */ jaroslav@601: public jaroslav@601: class DataOutputStream extends FilterOutputStream implements DataOutput { jaroslav@601: /** jaroslav@601: * The number of bytes written to the data output stream so far. jaroslav@601: * If this counter overflows, it will be wrapped to Integer.MAX_VALUE. jaroslav@601: */ jaroslav@601: protected int written; jaroslav@601: jaroslav@601: /** jaroslav@601: * bytearr is initialized on demand by writeUTF jaroslav@601: */ jaroslav@601: private byte[] bytearr = null; jaroslav@601: jaroslav@601: /** jaroslav@601: * Creates a new data output stream to write data to the specified jaroslav@601: * underlying output stream. The counter written is jaroslav@601: * set to zero. jaroslav@601: * jaroslav@601: * @param out the underlying output stream, to be saved for later jaroslav@601: * use. jaroslav@601: * @see java.io.FilterOutputStream#out jaroslav@601: */ jaroslav@601: public DataOutputStream(OutputStream out) { jaroslav@601: super(out); jaroslav@601: } jaroslav@601: jaroslav@601: /** jaroslav@601: * Increases the written counter by the specified value jaroslav@601: * until it reaches Integer.MAX_VALUE. jaroslav@601: */ jaroslav@601: private void incCount(int value) { jaroslav@601: int temp = written + value; jaroslav@601: if (temp < 0) { jaroslav@601: temp = Integer.MAX_VALUE; jaroslav@601: } jaroslav@601: written = temp; jaroslav@601: } jaroslav@601: jaroslav@601: /** jaroslav@601: * Writes the specified byte (the low eight bits of the argument jaroslav@601: * b) to the underlying output stream. If no exception jaroslav@601: * is thrown, the counter written is incremented by jaroslav@601: * 1. jaroslav@601: *

jaroslav@601: * Implements the write method of OutputStream. jaroslav@601: * jaroslav@601: * @param b the byte to be written. jaroslav@601: * @exception IOException if an I/O error occurs. jaroslav@601: * @see java.io.FilterOutputStream#out jaroslav@601: */ jaroslav@601: public synchronized void write(int b) throws IOException { jaroslav@601: out.write(b); jaroslav@601: incCount(1); jaroslav@601: } jaroslav@601: jaroslav@601: /** jaroslav@601: * Writes len bytes from the specified byte array jaroslav@601: * starting at offset off to the underlying output stream. jaroslav@601: * If no exception is thrown, the counter written is jaroslav@601: * incremented by len. jaroslav@601: * jaroslav@601: * @param b the data. jaroslav@601: * @param off the start offset in the data. jaroslav@601: * @param len the number of bytes to write. jaroslav@601: * @exception IOException if an I/O error occurs. jaroslav@601: * @see java.io.FilterOutputStream#out jaroslav@601: */ jaroslav@601: public synchronized void write(byte b[], int off, int len) jaroslav@601: throws IOException jaroslav@601: { jaroslav@601: out.write(b, off, len); jaroslav@601: incCount(len); jaroslav@601: } jaroslav@601: jaroslav@601: /** jaroslav@601: * Flushes this data output stream. This forces any buffered output jaroslav@601: * bytes to be written out to the stream. jaroslav@601: *

jaroslav@601: * The flush method of DataOutputStream jaroslav@601: * calls the flush method of its underlying output stream. jaroslav@601: * jaroslav@601: * @exception IOException if an I/O error occurs. jaroslav@601: * @see java.io.FilterOutputStream#out jaroslav@601: * @see java.io.OutputStream#flush() jaroslav@601: */ jaroslav@601: public void flush() throws IOException { jaroslav@601: out.flush(); jaroslav@601: } jaroslav@601: jaroslav@601: /** jaroslav@601: * Writes a boolean to the underlying output stream as jaroslav@601: * a 1-byte value. The value true is written out as the jaroslav@601: * value (byte)1; the value false is jaroslav@601: * written out as the value (byte)0. If no exception is jaroslav@601: * thrown, the counter written is incremented by jaroslav@601: * 1. jaroslav@601: * jaroslav@601: * @param v a boolean value to be written. jaroslav@601: * @exception IOException if an I/O error occurs. jaroslav@601: * @see java.io.FilterOutputStream#out jaroslav@601: */ jaroslav@601: public final void writeBoolean(boolean v) throws IOException { jaroslav@601: out.write(v ? 1 : 0); jaroslav@601: incCount(1); jaroslav@601: } jaroslav@601: jaroslav@601: /** jaroslav@601: * Writes out a byte to the underlying output stream as jaroslav@601: * a 1-byte value. If no exception is thrown, the counter jaroslav@601: * written is incremented by 1. jaroslav@601: * jaroslav@601: * @param v a byte value to be written. jaroslav@601: * @exception IOException if an I/O error occurs. jaroslav@601: * @see java.io.FilterOutputStream#out jaroslav@601: */ jaroslav@601: public final void writeByte(int v) throws IOException { jaroslav@601: out.write(v); jaroslav@601: incCount(1); jaroslav@601: } jaroslav@601: jaroslav@601: /** jaroslav@601: * Writes a short to the underlying output stream as two jaroslav@601: * bytes, high byte first. If no exception is thrown, the counter jaroslav@601: * written is incremented by 2. jaroslav@601: * jaroslav@601: * @param v a short to be written. jaroslav@601: * @exception IOException if an I/O error occurs. jaroslav@601: * @see java.io.FilterOutputStream#out jaroslav@601: */ jaroslav@601: public final void writeShort(int v) throws IOException { jaroslav@601: out.write((v >>> 8) & 0xFF); jaroslav@601: out.write((v >>> 0) & 0xFF); jaroslav@601: incCount(2); jaroslav@601: } jaroslav@601: jaroslav@601: /** jaroslav@601: * Writes a char to the underlying output stream as a jaroslav@601: * 2-byte value, high byte first. If no exception is thrown, the jaroslav@601: * counter written is incremented by 2. jaroslav@601: * jaroslav@601: * @param v a char value to be written. jaroslav@601: * @exception IOException if an I/O error occurs. jaroslav@601: * @see java.io.FilterOutputStream#out jaroslav@601: */ jaroslav@601: public final void writeChar(int v) throws IOException { jaroslav@601: out.write((v >>> 8) & 0xFF); jaroslav@601: out.write((v >>> 0) & 0xFF); jaroslav@601: incCount(2); jaroslav@601: } jaroslav@601: jaroslav@601: /** jaroslav@601: * Writes an int to the underlying output stream as four jaroslav@601: * bytes, high byte first. If no exception is thrown, the counter jaroslav@601: * written is incremented by 4. jaroslav@601: * jaroslav@601: * @param v an int to be written. jaroslav@601: * @exception IOException if an I/O error occurs. jaroslav@601: * @see java.io.FilterOutputStream#out jaroslav@601: */ jaroslav@601: public final void writeInt(int v) throws IOException { jaroslav@601: out.write((v >>> 24) & 0xFF); jaroslav@601: out.write((v >>> 16) & 0xFF); jaroslav@601: out.write((v >>> 8) & 0xFF); jaroslav@601: out.write((v >>> 0) & 0xFF); jaroslav@601: incCount(4); jaroslav@601: } jaroslav@601: jaroslav@601: private byte writeBuffer[] = new byte[8]; jaroslav@601: jaroslav@601: /** jaroslav@601: * Writes a long to the underlying output stream as eight jaroslav@601: * bytes, high byte first. In no exception is thrown, the counter jaroslav@601: * written is incremented by 8. jaroslav@601: * jaroslav@601: * @param v a long to be written. jaroslav@601: * @exception IOException if an I/O error occurs. jaroslav@601: * @see java.io.FilterOutputStream#out jaroslav@601: */ jaroslav@601: public final void writeLong(long v) throws IOException { jaroslav@601: writeBuffer[0] = (byte)(v >>> 56); jaroslav@601: writeBuffer[1] = (byte)(v >>> 48); jaroslav@601: writeBuffer[2] = (byte)(v >>> 40); jaroslav@601: writeBuffer[3] = (byte)(v >>> 32); jaroslav@601: writeBuffer[4] = (byte)(v >>> 24); jaroslav@601: writeBuffer[5] = (byte)(v >>> 16); jaroslav@601: writeBuffer[6] = (byte)(v >>> 8); jaroslav@601: writeBuffer[7] = (byte)(v >>> 0); jaroslav@601: out.write(writeBuffer, 0, 8); jaroslav@601: incCount(8); jaroslav@601: } jaroslav@601: jaroslav@601: /** jaroslav@601: * Converts the float argument to an int using the jaroslav@601: * floatToIntBits method in class Float, jaroslav@601: * and then writes that int value to the underlying jaroslav@601: * output stream as a 4-byte quantity, high byte first. If no jaroslav@601: * exception is thrown, the counter written is jaroslav@601: * incremented by 4. jaroslav@601: * jaroslav@601: * @param v a float value to be written. jaroslav@601: * @exception IOException if an I/O error occurs. jaroslav@601: * @see java.io.FilterOutputStream#out jaroslav@601: * @see java.lang.Float#floatToIntBits(float) jaroslav@601: */ jaroslav@601: public final void writeFloat(float v) throws IOException { jaroslav@601: writeInt(Float.floatToIntBits(v)); jaroslav@601: } jaroslav@601: jaroslav@601: /** jaroslav@601: * Converts the double argument to a long using the jaroslav@601: * doubleToLongBits method in class Double, jaroslav@601: * and then writes that long value to the underlying jaroslav@601: * output stream as an 8-byte quantity, high byte first. If no jaroslav@601: * exception is thrown, the counter written is jaroslav@601: * incremented by 8. jaroslav@601: * jaroslav@601: * @param v a double value to be written. jaroslav@601: * @exception IOException if an I/O error occurs. jaroslav@601: * @see java.io.FilterOutputStream#out jaroslav@601: * @see java.lang.Double#doubleToLongBits(double) jaroslav@601: */ jaroslav@601: public final void writeDouble(double v) throws IOException { jaroslav@601: writeLong(Double.doubleToLongBits(v)); jaroslav@601: } jaroslav@601: jaroslav@601: /** jaroslav@601: * Writes out the string to the underlying output stream as a jaroslav@601: * sequence of bytes. Each character in the string is written out, in jaroslav@601: * sequence, by discarding its high eight bits. If no exception is jaroslav@601: * thrown, the counter written is incremented by the jaroslav@601: * length of s. jaroslav@601: * jaroslav@601: * @param s a string of bytes to be written. jaroslav@601: * @exception IOException if an I/O error occurs. jaroslav@601: * @see java.io.FilterOutputStream#out jaroslav@601: */ jaroslav@601: public final void writeBytes(String s) throws IOException { jaroslav@601: int len = s.length(); jaroslav@601: for (int i = 0 ; i < len ; i++) { jaroslav@601: out.write((byte)s.charAt(i)); jaroslav@601: } jaroslav@601: incCount(len); jaroslav@601: } jaroslav@601: jaroslav@601: /** jaroslav@601: * Writes a string to the underlying output stream as a sequence of jaroslav@601: * characters. Each character is written to the data output stream as jaroslav@601: * if by the writeChar method. If no exception is jaroslav@601: * thrown, the counter written is incremented by twice jaroslav@601: * the length of s. jaroslav@601: * jaroslav@601: * @param s a String value to be written. jaroslav@601: * @exception IOException if an I/O error occurs. jaroslav@601: * @see java.io.DataOutputStream#writeChar(int) jaroslav@601: * @see java.io.FilterOutputStream#out jaroslav@601: */ jaroslav@601: public final void writeChars(String s) throws IOException { jaroslav@601: int len = s.length(); jaroslav@601: for (int i = 0 ; i < len ; i++) { jaroslav@601: int v = s.charAt(i); jaroslav@601: out.write((v >>> 8) & 0xFF); jaroslav@601: out.write((v >>> 0) & 0xFF); jaroslav@601: } jaroslav@601: incCount(len * 2); jaroslav@601: } jaroslav@601: jaroslav@601: /** jaroslav@601: * Writes a string to the underlying output stream using jaroslav@601: * modified UTF-8 jaroslav@601: * encoding in a machine-independent manner. jaroslav@601: *

jaroslav@601: * First, two bytes are written to the output stream as if by the jaroslav@601: * writeShort method giving the number of bytes to jaroslav@601: * follow. This value is the number of bytes actually written out, jaroslav@601: * not the length of the string. Following the length, each character jaroslav@601: * of the string is output, in sequence, using the modified UTF-8 encoding jaroslav@601: * for the character. If no exception is thrown, the counter jaroslav@601: * written is incremented by the total number of jaroslav@601: * bytes written to the output stream. This will be at least two jaroslav@601: * plus the length of str, and at most two plus jaroslav@601: * thrice the length of str. jaroslav@601: * jaroslav@601: * @param str a string to be written. jaroslav@601: * @exception IOException if an I/O error occurs. jaroslav@601: */ jaroslav@601: public final void writeUTF(String str) throws IOException { jaroslav@601: writeUTF(str, this); jaroslav@601: } jaroslav@601: jaroslav@601: /** jaroslav@601: * Writes a string to the specified DataOutput using jaroslav@601: * modified UTF-8 jaroslav@601: * encoding in a machine-independent manner. jaroslav@601: *

jaroslav@601: * First, two bytes are written to out as if by the writeShort jaroslav@601: * method giving the number of bytes to follow. This value is the number of jaroslav@601: * bytes actually written out, not the length of the string. Following the jaroslav@601: * length, each character of the string is output, in sequence, using the jaroslav@601: * modified UTF-8 encoding for the character. If no exception is thrown, the jaroslav@601: * counter written is incremented by the total number of jaroslav@601: * bytes written to the output stream. This will be at least two jaroslav@601: * plus the length of str, and at most two plus jaroslav@601: * thrice the length of str. jaroslav@601: * jaroslav@601: * @param str a string to be written. jaroslav@601: * @param out destination to write to jaroslav@601: * @return The number of bytes written out. jaroslav@601: * @exception IOException if an I/O error occurs. jaroslav@601: */ jaroslav@601: static int writeUTF(String str, DataOutput out) throws IOException { jaroslav@601: int strlen = str.length(); jaroslav@601: int utflen = 0; jaroslav@601: int c, count = 0; jaroslav@601: jaroslav@601: /* use charAt instead of copying String to char array */ jaroslav@601: for (int i = 0; i < strlen; i++) { jaroslav@601: c = str.charAt(i); jaroslav@601: if ((c >= 0x0001) && (c <= 0x007F)) { jaroslav@601: utflen++; jaroslav@601: } else if (c > 0x07FF) { jaroslav@601: utflen += 3; jaroslav@601: } else { jaroslav@601: utflen += 2; jaroslav@601: } jaroslav@601: } jaroslav@601: jaroslav@601: if (utflen > 65535) jaroslav@601: throw new UTFDataFormatException( jaroslav@601: "encoded string too long: " + utflen + " bytes"); jaroslav@601: jaroslav@601: byte[] bytearr = null; jaroslav@601: if (out instanceof DataOutputStream) { jaroslav@601: DataOutputStream dos = (DataOutputStream)out; jaroslav@601: if(dos.bytearr == null || (dos.bytearr.length < (utflen+2))) jaroslav@601: dos.bytearr = new byte[(utflen*2) + 2]; jaroslav@601: bytearr = dos.bytearr; jaroslav@601: } else { jaroslav@601: bytearr = new byte[utflen+2]; jaroslav@601: } jaroslav@601: jaroslav@601: bytearr[count++] = (byte) ((utflen >>> 8) & 0xFF); jaroslav@601: bytearr[count++] = (byte) ((utflen >>> 0) & 0xFF); jaroslav@601: jaroslav@601: int i=0; jaroslav@601: for (i=0; i= 0x0001) && (c <= 0x007F))) break; jaroslav@601: bytearr[count++] = (byte) c; jaroslav@601: } jaroslav@601: jaroslav@601: for (;i < strlen; i++){ jaroslav@601: c = str.charAt(i); jaroslav@601: if ((c >= 0x0001) && (c <= 0x007F)) { jaroslav@601: bytearr[count++] = (byte) c; jaroslav@601: jaroslav@601: } else if (c > 0x07FF) { jaroslav@601: bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F)); jaroslav@601: bytearr[count++] = (byte) (0x80 | ((c >> 6) & 0x3F)); jaroslav@601: bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F)); jaroslav@601: } else { jaroslav@601: bytearr[count++] = (byte) (0xC0 | ((c >> 6) & 0x1F)); jaroslav@601: bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F)); jaroslav@601: } jaroslav@601: } jaroslav@601: out.write(bytearr, 0, utflen+2); jaroslav@601: return utflen + 2; jaroslav@601: } jaroslav@601: jaroslav@601: /** jaroslav@601: * Returns the current value of the counter written, jaroslav@601: * the number of bytes written to this data output stream so far. jaroslav@601: * If the counter overflows, it will be wrapped to Integer.MAX_VALUE. jaroslav@601: * jaroslav@601: * @return the value of the written field. jaroslav@601: * @see java.io.DataOutputStream#written jaroslav@601: */ jaroslav@601: public final int size() { jaroslav@601: return written; jaroslav@601: } jaroslav@601: }