001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package java.io;
019:
020: import org.apache.harmony.luni.util.Msg;
021:
022: /**
023: * DataOutputStream is a filter class which can write typed data to a Stream.
024: * Typically, this stream can be read in by a DataInputStream. Types that can be
025: * written include byte, 16-bit short, 32-bit int, 32-bit float, 64-bit long,
026: * 64-bit double, byte strings, and UTF Strings.
027: *
028: * @see DataInputStream
029: */
030: public class DataOutputStream extends FilterOutputStream implements
031: DataOutput {
032:
033: /** The number of bytes written out so far */
034: protected int written;
035: byte buff[];
036:
037: /**
038: * Constructs a new DataOutputStream on the OutputStream <code>out</code>.
039: * All writes can now be filtered through this stream. Note that data
040: * written by this Stream is not in a human readable format but can be
041: * reconstructed by using a DataInputStream on the resulting output.
042: *
043: * @param out
044: * the target OutputStream to filter writes on.
045: */
046: public DataOutputStream(OutputStream out) {
047: super (out);
048: buff = new byte[8];
049: }
050:
051: /**
052: * Flush this DataOutputStream to ensure all pending data is sent out to the
053: * target OutputStream. This implementation flushes the target OutputStream.
054: *
055: * @throws IOException
056: * If an error occurs attempting to flush this DataOutputStream.
057: */
058: @Override
059: public void flush() throws IOException {
060: super .flush();
061: }
062:
063: /**
064: * Answers the total number of bytes written to this stream thus far.
065: *
066: * @return the number of bytes written to this DataOutputStream.
067: */
068: public final int size() {
069: if (written < 0) {
070: written = Integer.MAX_VALUE;
071: }
072: return written;
073: }
074:
075: /**
076: * Writes <code>count</code> <code>bytes</code> from the byte array
077: * <code>buffer</code> starting at offset <code>index</code> to the
078: * OutputStream.
079: *
080: * @param buffer
081: * the buffer to be written
082: * @param offset
083: * offset in buffer to get bytes
084: * @param count
085: * number of bytes in buffer to write
086: *
087: * @throws IOException
088: * If an error occurs attempting to write to this
089: * DataOutputStream.
090: *
091: * @see DataInput#readFully(byte[])
092: * @see DataInput#readFully(byte[], int, int)
093: */
094: @Override
095: public void write(byte buffer[], int offset, int count)
096: throws IOException {
097: if (buffer == null) {
098: throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
099: }
100: out.write(buffer, offset, count);
101: written += count;
102: }
103:
104: /**
105: * Writes the specified <code>byte</code> to the OutputStream.
106: *
107: * @param oneByte
108: * the byte to be written
109: *
110: * @throws IOException
111: * If an error occurs attempting to write to this
112: * DataOutputStream.
113: *
114: * @see DataInput#readByte()
115: */
116: @Override
117: public void write(int oneByte) throws IOException {
118: out.write(oneByte);
119: written++;
120: }
121:
122: /**
123: * Writes a boolean to this output stream.
124: *
125: * @param val
126: * the boolean value to write to the OutputStream
127: *
128: * @throws IOException
129: * If an error occurs attempting to write to this
130: * DataOutputStream.
131: *
132: * @see DataInput#readBoolean()
133: */
134: public final void writeBoolean(boolean val) throws IOException {
135: out.write(val ? 1 : 0);
136: written++;
137: }
138:
139: /**
140: * Writes a 8-bit byte to this output stream.
141: *
142: * @param val
143: * the byte value to write to the OutputStream
144: *
145: * @throws IOException
146: * If an error occurs attempting to write to this
147: * DataOutputStream.
148: *
149: * @see DataInput#readByte()
150: * @see DataInput#readUnsignedByte()
151: */
152: public final void writeByte(int val) throws IOException {
153: out.write(val);
154: written++;
155: }
156:
157: /**
158: * Writes the low order 8-bit bytes from a String to this output stream.
159: *
160: * @param str
161: * the String containing the bytes to write to the OutputStream
162: *
163: * @throws IOException
164: * If an error occurs attempting to write to this
165: * DataOutputStream.
166: *
167: * @see DataInput#readFully(byte[])
168: * @see DataInput#readFully(byte[],int,int)
169: */
170: public final void writeBytes(String str) throws IOException {
171: if (str.length() == 0) {
172: return;
173: }
174: byte bytes[] = new byte[str.length()];
175: for (int index = 0; index < str.length(); index++) {
176: bytes[index] = (byte) str.charAt(index);
177: }
178: out.write(bytes);
179: written += bytes.length;
180: }
181:
182: /**
183: * Writes the specified 16-bit character to the OutputStream. Only the lower
184: * 2 bytes are written with the higher of the 2 bytes written first. This
185: * represents the Unicode value of val.
186: *
187: * @param val
188: * the character to be written
189: *
190: * @throws IOException
191: * If an error occurs attempting to write to this
192: * DataOutputStream.
193: *
194: * @see DataInput#readChar()
195: */
196: public final void writeChar(int val) throws IOException {
197: buff[0] = (byte) (val >> 8);
198: buff[1] = (byte) val;
199: out.write(buff, 0, 2);
200: written += 2;
201: }
202:
203: /**
204: * Writes the specified 16-bit characters contained in str to the
205: * OutputStream. Only the lower 2 bytes of each character are written with
206: * the higher of the 2 bytes written first. This represents the Unicode
207: * value of each character in str.
208: *
209: * @param str
210: * the String whose characters are to be written.
211: *
212: * @throws IOException
213: * If an error occurs attempting to write to this
214: * DataOutputStream.
215: *
216: * @see DataInput#readChar()
217: */
218: public final void writeChars(String str) throws IOException {
219: byte newBytes[] = new byte[str.length() * 2];
220: for (int index = 0; index < str.length(); index++) {
221: int newIndex = index == 0 ? index : index * 2;
222: newBytes[newIndex] = (byte) (str.charAt(index) >> 8);
223: newBytes[newIndex + 1] = (byte) str.charAt(index);
224: }
225: out.write(newBytes);
226: written += newBytes.length;
227: }
228:
229: /**
230: * Writes a 64-bit double to this output stream. The resulting output is the
231: * 8 bytes resulting from calling Double.doubleToLongBits().
232: *
233: * @param val
234: * the double to be written.
235: *
236: * @throws IOException
237: * If an error occurs attempting to write to this
238: * DataOutputStream.
239: *
240: * @see DataInput#readDouble()
241: */
242: public final void writeDouble(double val) throws IOException {
243: writeLong(Double.doubleToLongBits(val));
244: }
245:
246: /**
247: * Writes a 32-bit float to this output stream. The resulting output is the
248: * 4 bytes resulting from calling Float.floatToIntBits().
249: *
250: * @param val
251: * the float to be written.
252: *
253: * @throws IOException
254: * If an error occurs attempting to write to this
255: * DataOutputStream.
256: *
257: * @see DataInput#readFloat()
258: */
259: public final void writeFloat(float val) throws IOException {
260: writeInt(Float.floatToIntBits(val));
261: }
262:
263: /**
264: * Writes a 32-bit int to this output stream. The resulting output is the 4
265: * bytes, highest order first, of val.
266: *
267: * @param val
268: * the int to be written.
269: *
270: * @throws IOException
271: * If an error occurs attempting to write to this
272: * DataOutputStream.
273: *
274: * @see DataInput#readInt()
275: */
276: public final void writeInt(int val) throws IOException {
277: buff[0] = (byte) (val >> 24);
278: buff[1] = (byte) (val >> 16);
279: buff[2] = (byte) (val >> 8);
280: buff[3] = (byte) val;
281: out.write(buff, 0, 4);
282: written += 4;
283: }
284:
285: /**
286: * Writes a 64-bit long to this output stream. The resulting output is the 8
287: * bytes, highest order first, of val.
288: *
289: * @param val
290: * the long to be written.
291: *
292: * @throws IOException
293: * If an error occurs attempting to write to this
294: * DataOutputStream.
295: *
296: * @see DataInput#readLong()
297: */
298: public final void writeLong(long val) throws IOException {
299: buff[0] = (byte) (val >> 56);
300: buff[1] = (byte) (val >> 48);
301: buff[2] = (byte) (val >> 40);
302: buff[3] = (byte) (val >> 32);
303: buff[4] = (byte) (val >> 24);
304: buff[5] = (byte) (val >> 16);
305: buff[6] = (byte) (val >> 8);
306: buff[7] = (byte) val;
307: out.write(buff, 0, 8);
308: written += 8;
309: }
310:
311: /**
312: * Writes the specified 16-bit short to the OutputStream. Only the lower 2
313: * bytes are written with the higher of the 2 bytes written first.
314: *
315: * @param val
316: * the short to be written
317: *
318: * @throws IOException
319: * If an error occurs attempting to write to this
320: * DataOutputStream.
321: *
322: * @see DataInput#readShort()
323: * @see DataInput#readUnsignedShort()
324: */
325: public final void writeShort(int val) throws IOException {
326: buff[0] = (byte) (val >> 8);
327: buff[1] = (byte) val;
328: out.write(buff, 0, 2);
329: written += 2;
330: }
331:
332: /**
333: * Writes the specified String out in UTF format.
334: *
335: * @param str
336: * the String to be written in UTF format.
337: *
338: * @throws IOException
339: * If an error occurs attempting to write to this
340: * DataOutputStream.
341: *
342: * @see DataInput#readUTF()
343: */
344: public final void writeUTF(String str) throws IOException {
345: long utfCount = countUTFBytes(str);
346: if (utfCount > 65535) {
347: throw new UTFDataFormatException(Msg.getString("K0068")); //$NON-NLS-1$
348: }
349: writeShort((int) utfCount);
350: writeUTFBytes(str, utfCount);
351: }
352:
353: long countUTFBytes(String str) {
354: int utfCount = 0, length = str.length();
355: for (int i = 0; i < length; i++) {
356: int charValue = str.charAt(i);
357: if (charValue > 0 && charValue <= 127) {
358: utfCount++;
359: } else if (charValue <= 2047) {
360: utfCount += 2;
361: } else {
362: utfCount += 3;
363: }
364: }
365: return utfCount;
366: }
367:
368: void writeUTFBytes(String str, long count) throws IOException {
369: int size = (int) count;
370: int length = str.length();
371: byte[] utfBytes = new byte[size];
372: int utfIndex = 0;
373: for (int i = 0; i < length; i++) {
374: int charValue = str.charAt(i);
375: if (charValue > 0 && charValue <= 127) {
376: utfBytes[utfIndex++] = (byte) charValue;
377: } else if (charValue <= 2047) {
378: utfBytes[utfIndex++] = (byte) (0xc0 | (0x1f & (charValue >> 6)));
379: utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & charValue));
380: } else {
381: utfBytes[utfIndex++] = (byte) (0xe0 | (0x0f & (charValue >> 12)));
382: utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & (charValue >> 6)));
383: utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & charValue));
384: }
385: }
386: write(utfBytes, 0, utfIndex);
387: }
388: }
|