rt/emul/compact/src/main/java/java/io/DataOutputStream.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Tue, 26 Feb 2013 16:54:16 +0100
changeset 772 d382dacfd73f
parent 601 emul/compact/src/main/java/java/io/DataOutputStream.java@5198affdb915
permissions -rw-r--r--
Moving modules around so the runtime is under one master pom and can be built without building other modules that are in the repository
     1 /*
     2  * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    25 
    26 package java.io;
    27 
    28 /**
    29  * A data output stream lets an application write primitive Java data
    30  * types to an output stream in a portable way. An application can
    31  * then use a data input stream to read the data back in.
    32  *
    33  * @author  unascribed
    34  * @see     java.io.DataInputStream
    35  * @since   JDK1.0
    36  */
    37 public
    38 class DataOutputStream extends FilterOutputStream implements DataOutput {
    39     /**
    40      * The number of bytes written to the data output stream so far.
    41      * If this counter overflows, it will be wrapped to Integer.MAX_VALUE.
    42      */
    43     protected int written;
    44 
    45     /**
    46      * bytearr is initialized on demand by writeUTF
    47      */
    48     private byte[] bytearr = null;
    49 
    50     /**
    51      * Creates a new data output stream to write data to the specified
    52      * underlying output stream. The counter <code>written</code> is
    53      * set to zero.
    54      *
    55      * @param   out   the underlying output stream, to be saved for later
    56      *                use.
    57      * @see     java.io.FilterOutputStream#out
    58      */
    59     public DataOutputStream(OutputStream out) {
    60         super(out);
    61     }
    62 
    63     /**
    64      * Increases the written counter by the specified value
    65      * until it reaches Integer.MAX_VALUE.
    66      */
    67     private void incCount(int value) {
    68         int temp = written + value;
    69         if (temp < 0) {
    70             temp = Integer.MAX_VALUE;
    71         }
    72         written = temp;
    73     }
    74 
    75     /**
    76      * Writes the specified byte (the low eight bits of the argument
    77      * <code>b</code>) to the underlying output stream. If no exception
    78      * is thrown, the counter <code>written</code> is incremented by
    79      * <code>1</code>.
    80      * <p>
    81      * Implements the <code>write</code> method of <code>OutputStream</code>.
    82      *
    83      * @param      b   the <code>byte</code> to be written.
    84      * @exception  IOException  if an I/O error occurs.
    85      * @see        java.io.FilterOutputStream#out
    86      */
    87     public synchronized void write(int b) throws IOException {
    88         out.write(b);
    89         incCount(1);
    90     }
    91 
    92     /**
    93      * Writes <code>len</code> bytes from the specified byte array
    94      * starting at offset <code>off</code> to the underlying output stream.
    95      * If no exception is thrown, the counter <code>written</code> is
    96      * incremented by <code>len</code>.
    97      *
    98      * @param      b     the data.
    99      * @param      off   the start offset in the data.
   100      * @param      len   the number of bytes to write.
   101      * @exception  IOException  if an I/O error occurs.
   102      * @see        java.io.FilterOutputStream#out
   103      */
   104     public synchronized void write(byte b[], int off, int len)
   105         throws IOException
   106     {
   107         out.write(b, off, len);
   108         incCount(len);
   109     }
   110 
   111     /**
   112      * Flushes this data output stream. This forces any buffered output
   113      * bytes to be written out to the stream.
   114      * <p>
   115      * The <code>flush</code> method of <code>DataOutputStream</code>
   116      * calls the <code>flush</code> method of its underlying output stream.
   117      *
   118      * @exception  IOException  if an I/O error occurs.
   119      * @see        java.io.FilterOutputStream#out
   120      * @see        java.io.OutputStream#flush()
   121      */
   122     public void flush() throws IOException {
   123         out.flush();
   124     }
   125 
   126     /**
   127      * Writes a <code>boolean</code> to the underlying output stream as
   128      * a 1-byte value. The value <code>true</code> is written out as the
   129      * value <code>(byte)1</code>; the value <code>false</code> is
   130      * written out as the value <code>(byte)0</code>. If no exception is
   131      * thrown, the counter <code>written</code> is incremented by
   132      * <code>1</code>.
   133      *
   134      * @param      v   a <code>boolean</code> value to be written.
   135      * @exception  IOException  if an I/O error occurs.
   136      * @see        java.io.FilterOutputStream#out
   137      */
   138     public final void writeBoolean(boolean v) throws IOException {
   139         out.write(v ? 1 : 0);
   140         incCount(1);
   141     }
   142 
   143     /**
   144      * Writes out a <code>byte</code> to the underlying output stream as
   145      * a 1-byte value. If no exception is thrown, the counter
   146      * <code>written</code> is incremented by <code>1</code>.
   147      *
   148      * @param      v   a <code>byte</code> value to be written.
   149      * @exception  IOException  if an I/O error occurs.
   150      * @see        java.io.FilterOutputStream#out
   151      */
   152     public final void writeByte(int v) throws IOException {
   153         out.write(v);
   154         incCount(1);
   155     }
   156 
   157     /**
   158      * Writes a <code>short</code> to the underlying output stream as two
   159      * bytes, high byte first. If no exception is thrown, the counter
   160      * <code>written</code> is incremented by <code>2</code>.
   161      *
   162      * @param      v   a <code>short</code> to be written.
   163      * @exception  IOException  if an I/O error occurs.
   164      * @see        java.io.FilterOutputStream#out
   165      */
   166     public final void writeShort(int v) throws IOException {
   167         out.write((v >>> 8) & 0xFF);
   168         out.write((v >>> 0) & 0xFF);
   169         incCount(2);
   170     }
   171 
   172     /**
   173      * Writes a <code>char</code> to the underlying output stream as a
   174      * 2-byte value, high byte first. If no exception is thrown, the
   175      * counter <code>written</code> is incremented by <code>2</code>.
   176      *
   177      * @param      v   a <code>char</code> value to be written.
   178      * @exception  IOException  if an I/O error occurs.
   179      * @see        java.io.FilterOutputStream#out
   180      */
   181     public final void writeChar(int v) throws IOException {
   182         out.write((v >>> 8) & 0xFF);
   183         out.write((v >>> 0) & 0xFF);
   184         incCount(2);
   185     }
   186 
   187     /**
   188      * Writes an <code>int</code> to the underlying output stream as four
   189      * bytes, high byte first. If no exception is thrown, the counter
   190      * <code>written</code> is incremented by <code>4</code>.
   191      *
   192      * @param      v   an <code>int</code> to be written.
   193      * @exception  IOException  if an I/O error occurs.
   194      * @see        java.io.FilterOutputStream#out
   195      */
   196     public final void writeInt(int v) throws IOException {
   197         out.write((v >>> 24) & 0xFF);
   198         out.write((v >>> 16) & 0xFF);
   199         out.write((v >>>  8) & 0xFF);
   200         out.write((v >>>  0) & 0xFF);
   201         incCount(4);
   202     }
   203 
   204     private byte writeBuffer[] = new byte[8];
   205 
   206     /**
   207      * Writes a <code>long</code> to the underlying output stream as eight
   208      * bytes, high byte first. In no exception is thrown, the counter
   209      * <code>written</code> is incremented by <code>8</code>.
   210      *
   211      * @param      v   a <code>long</code> to be written.
   212      * @exception  IOException  if an I/O error occurs.
   213      * @see        java.io.FilterOutputStream#out
   214      */
   215     public final void writeLong(long v) throws IOException {
   216         writeBuffer[0] = (byte)(v >>> 56);
   217         writeBuffer[1] = (byte)(v >>> 48);
   218         writeBuffer[2] = (byte)(v >>> 40);
   219         writeBuffer[3] = (byte)(v >>> 32);
   220         writeBuffer[4] = (byte)(v >>> 24);
   221         writeBuffer[5] = (byte)(v >>> 16);
   222         writeBuffer[6] = (byte)(v >>>  8);
   223         writeBuffer[7] = (byte)(v >>>  0);
   224         out.write(writeBuffer, 0, 8);
   225         incCount(8);
   226     }
   227 
   228     /**
   229      * Converts the float argument to an <code>int</code> using the
   230      * <code>floatToIntBits</code> method in class <code>Float</code>,
   231      * and then writes that <code>int</code> value to the underlying
   232      * output stream as a 4-byte quantity, high byte first. If no
   233      * exception is thrown, the counter <code>written</code> is
   234      * incremented by <code>4</code>.
   235      *
   236      * @param      v   a <code>float</code> value to be written.
   237      * @exception  IOException  if an I/O error occurs.
   238      * @see        java.io.FilterOutputStream#out
   239      * @see        java.lang.Float#floatToIntBits(float)
   240      */
   241     public final void writeFloat(float v) throws IOException {
   242         writeInt(Float.floatToIntBits(v));
   243     }
   244 
   245     /**
   246      * Converts the double argument to a <code>long</code> using the
   247      * <code>doubleToLongBits</code> method in class <code>Double</code>,
   248      * and then writes that <code>long</code> value to the underlying
   249      * output stream as an 8-byte quantity, high byte first. If no
   250      * exception is thrown, the counter <code>written</code> is
   251      * incremented by <code>8</code>.
   252      *
   253      * @param      v   a <code>double</code> value to be written.
   254      * @exception  IOException  if an I/O error occurs.
   255      * @see        java.io.FilterOutputStream#out
   256      * @see        java.lang.Double#doubleToLongBits(double)
   257      */
   258     public final void writeDouble(double v) throws IOException {
   259         writeLong(Double.doubleToLongBits(v));
   260     }
   261 
   262     /**
   263      * Writes out the string to the underlying output stream as a
   264      * sequence of bytes. Each character in the string is written out, in
   265      * sequence, by discarding its high eight bits. If no exception is
   266      * thrown, the counter <code>written</code> is incremented by the
   267      * length of <code>s</code>.
   268      *
   269      * @param      s   a string of bytes to be written.
   270      * @exception  IOException  if an I/O error occurs.
   271      * @see        java.io.FilterOutputStream#out
   272      */
   273     public final void writeBytes(String s) throws IOException {
   274         int len = s.length();
   275         for (int i = 0 ; i < len ; i++) {
   276             out.write((byte)s.charAt(i));
   277         }
   278         incCount(len);
   279     }
   280 
   281     /**
   282      * Writes a string to the underlying output stream as a sequence of
   283      * characters. Each character is written to the data output stream as
   284      * if by the <code>writeChar</code> method. If no exception is
   285      * thrown, the counter <code>written</code> is incremented by twice
   286      * the length of <code>s</code>.
   287      *
   288      * @param      s   a <code>String</code> value to be written.
   289      * @exception  IOException  if an I/O error occurs.
   290      * @see        java.io.DataOutputStream#writeChar(int)
   291      * @see        java.io.FilterOutputStream#out
   292      */
   293     public final void writeChars(String s) throws IOException {
   294         int len = s.length();
   295         for (int i = 0 ; i < len ; i++) {
   296             int v = s.charAt(i);
   297             out.write((v >>> 8) & 0xFF);
   298             out.write((v >>> 0) & 0xFF);
   299         }
   300         incCount(len * 2);
   301     }
   302 
   303     /**
   304      * Writes a string to the underlying output stream using
   305      * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
   306      * encoding in a machine-independent manner.
   307      * <p>
   308      * First, two bytes are written to the output stream as if by the
   309      * <code>writeShort</code> method giving the number of bytes to
   310      * follow. This value is the number of bytes actually written out,
   311      * not the length of the string. Following the length, each character
   312      * of the string is output, in sequence, using the modified UTF-8 encoding
   313      * for the character. If no exception is thrown, the counter
   314      * <code>written</code> is incremented by the total number of
   315      * bytes written to the output stream. This will be at least two
   316      * plus the length of <code>str</code>, and at most two plus
   317      * thrice the length of <code>str</code>.
   318      *
   319      * @param      str   a string to be written.
   320      * @exception  IOException  if an I/O error occurs.
   321      */
   322     public final void writeUTF(String str) throws IOException {
   323         writeUTF(str, this);
   324     }
   325 
   326     /**
   327      * Writes a string to the specified DataOutput using
   328      * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
   329      * encoding in a machine-independent manner.
   330      * <p>
   331      * First, two bytes are written to out as if by the <code>writeShort</code>
   332      * method giving the number of bytes to follow. This value is the number of
   333      * bytes actually written out, not the length of the string. Following the
   334      * length, each character of the string is output, in sequence, using the
   335      * modified UTF-8 encoding for the character. If no exception is thrown, the
   336      * counter <code>written</code> is incremented by the total number of
   337      * bytes written to the output stream. This will be at least two
   338      * plus the length of <code>str</code>, and at most two plus
   339      * thrice the length of <code>str</code>.
   340      *
   341      * @param      str   a string to be written.
   342      * @param      out   destination to write to
   343      * @return     The number of bytes written out.
   344      * @exception  IOException  if an I/O error occurs.
   345      */
   346     static int writeUTF(String str, DataOutput out) throws IOException {
   347         int strlen = str.length();
   348         int utflen = 0;
   349         int c, count = 0;
   350 
   351         /* use charAt instead of copying String to char array */
   352         for (int i = 0; i < strlen; i++) {
   353             c = str.charAt(i);
   354             if ((c >= 0x0001) && (c <= 0x007F)) {
   355                 utflen++;
   356             } else if (c > 0x07FF) {
   357                 utflen += 3;
   358             } else {
   359                 utflen += 2;
   360             }
   361         }
   362 
   363         if (utflen > 65535)
   364             throw new UTFDataFormatException(
   365                 "encoded string too long: " + utflen + " bytes");
   366 
   367         byte[] bytearr = null;
   368         if (out instanceof DataOutputStream) {
   369             DataOutputStream dos = (DataOutputStream)out;
   370             if(dos.bytearr == null || (dos.bytearr.length < (utflen+2)))
   371                 dos.bytearr = new byte[(utflen*2) + 2];
   372             bytearr = dos.bytearr;
   373         } else {
   374             bytearr = new byte[utflen+2];
   375         }
   376 
   377         bytearr[count++] = (byte) ((utflen >>> 8) & 0xFF);
   378         bytearr[count++] = (byte) ((utflen >>> 0) & 0xFF);
   379 
   380         int i=0;
   381         for (i=0; i<strlen; i++) {
   382            c = str.charAt(i);
   383            if (!((c >= 0x0001) && (c <= 0x007F))) break;
   384            bytearr[count++] = (byte) c;
   385         }
   386 
   387         for (;i < strlen; i++){
   388             c = str.charAt(i);
   389             if ((c >= 0x0001) && (c <= 0x007F)) {
   390                 bytearr[count++] = (byte) c;
   391 
   392             } else if (c > 0x07FF) {
   393                 bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
   394                 bytearr[count++] = (byte) (0x80 | ((c >>  6) & 0x3F));
   395                 bytearr[count++] = (byte) (0x80 | ((c >>  0) & 0x3F));
   396             } else {
   397                 bytearr[count++] = (byte) (0xC0 | ((c >>  6) & 0x1F));
   398                 bytearr[count++] = (byte) (0x80 | ((c >>  0) & 0x3F));
   399             }
   400         }
   401         out.write(bytearr, 0, utflen+2);
   402         return utflen + 2;
   403     }
   404 
   405     /**
   406      * Returns the current value of the counter <code>written</code>,
   407      * the number of bytes written to this data output stream so far.
   408      * If the counter overflows, it will be wrapped to Integer.MAX_VALUE.
   409      *
   410      * @return  the value of the <code>written</code> field.
   411      * @see     java.io.DataOutputStream#written
   412      */
   413     public final int size() {
   414         return written;
   415     }
   416 }