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; iwritten
,
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: }