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: import org.apache.harmony.luni.util.Util;
022:
023: /**
024: * DataInputStream is a filter class which can read typed data from a Stream.
025: * Typically, this stream has been written by a DataOutputStream. Types that can
026: * be read include byte, 16-bit short, 32-bit int, 32-bit float, 64-bit long,
027: * 64-bit double, byte strings, and UTF Strings.
028: *
029: * @see DataOutputStream
030: */
031: public class DataInputStream extends FilterInputStream implements
032: DataInput {
033:
034: byte[] buff;
035:
036: /**
037: * Constructs a new DataInputStream on the InputStream <code>in</code>.
038: * All reads can now be filtered through this stream. Note that data read by
039: * this Stream is not in a human readable format and was most likely created
040: * by a DataOutputStream.
041: *
042: * @param in
043: * the target InputStream to filter reads on.
044: *
045: * @see DataOutputStream
046: * @see RandomAccessFile
047: */
048: public DataInputStream(InputStream in) {
049: super (in);
050: buff = new byte[8];
051: }
052:
053: /**
054: * Reads bytes from the source stream into the byte array
055: * <code>buffer</code>. The number of bytes actually read is returned.
056: *
057: * @param buffer
058: * the buffer to read bytes into
059: * @return the number of bytes actually read or -1 if end of stream.
060: *
061: * @throws IOException
062: * If a problem occurs reading from this DataInputStream.
063: *
064: * @see DataOutput#write(byte[])
065: * @see DataOutput#write(byte[], int, int)
066: */
067: @Override
068: public final int read(byte[] buffer) throws IOException {
069: return in.read(buffer, 0, buffer.length);
070: }
071:
072: /**
073: * Read at most <code>length</code> bytes from this DataInputStream and
074: * stores them in byte array <code>buffer</code> starting at
075: * <code>offset</code>. Answer the number of bytes actually read or -1 if
076: * no bytes were read and end of stream was encountered.
077: *
078: * @param buffer
079: * the byte array in which to store the read bytes.
080: * @param offset
081: * the offset in <code>buffer</code> to store the read bytes.
082: * @param length
083: * the maximum number of bytes to store in <code>buffer</code>.
084: * @return the number of bytes actually read or -1 if end of stream.
085: *
086: * @throws IOException
087: * If a problem occurs reading from this DataInputStream.
088: *
089: * @see DataOutput#write(byte[])
090: * @see DataOutput#write(byte[], int, int)
091: */
092: @Override
093: public final int read(byte[] buffer, int offset, int length)
094: throws IOException {
095: return in.read(buffer, offset, length);
096: }
097:
098: /**
099: * Reads a boolean from this stream.
100: *
101: * @return the next boolean value from the source stream.
102: *
103: * @throws IOException
104: * If a problem occurs reading from this DataInputStream.
105: *
106: * @see DataOutput#writeBoolean(boolean)
107: */
108: public final boolean readBoolean() throws IOException {
109: int temp = in.read();
110: if (temp < 0) {
111: throw new EOFException();
112: }
113: return temp != 0;
114: }
115:
116: /**
117: * Reads an 8-bit byte value from this stream.
118: *
119: * @return the next byte value from the source stream.
120: *
121: * @throws IOException
122: * If a problem occurs reading from this DataInputStream.
123: *
124: * @see DataOutput#writeByte(int)
125: */
126: public final byte readByte() throws IOException {
127: int temp = in.read();
128: if (temp < 0) {
129: throw new EOFException();
130: }
131: return (byte) temp;
132: }
133:
134: /**
135: * Reads a 16-bit character value from this stream.
136: *
137: * @return the next <code>char</code> value from the source stream.
138: *
139: * @throws IOException
140: * If a problem occurs reading from this DataInputStream.
141: *
142: * @see DataOutput#writeChar(int)
143: */
144: private int readToBuff(int count) throws IOException {
145: int offset = 0;
146:
147: while (offset < count) {
148: int bytesRead = in.read(buff, offset, count - offset);
149: if (bytesRead == -1)
150: return bytesRead;
151: offset += bytesRead;
152: }
153: return offset;
154: }
155:
156: public final char readChar() throws IOException {
157: if (readToBuff(2) < 0) {
158: throw new EOFException();
159: }
160: return (char) (((buff[0] & 0xff) << 8) | (buff[1] & 0xff));
161:
162: }
163:
164: /**
165: * Reads a 64-bit <code>double</code> value from this stream.
166: *
167: * @return the next <code>double</code> value from the source stream.
168: *
169: * @throws IOException
170: * If a problem occurs reading from this DataInputStream.
171: *
172: * @see DataOutput#writeDouble(double)
173: */
174: public final double readDouble() throws IOException {
175: return Double.longBitsToDouble(readLong());
176: }
177:
178: /**
179: * Reads a 32-bit <code>float</code> value from this stream.
180: *
181: * @return the next <code>float</code> value from the source stream.
182: *
183: * @throws IOException
184: * If a problem occurs reading from this DataInputStream.
185: *
186: * @see DataOutput#writeFloat(float)
187: */
188: public final float readFloat() throws IOException {
189: return Float.intBitsToFloat(readInt());
190: }
191:
192: /**
193: * Reads bytes from this stream into the byte array <code>buffer</code>.
194: * This method will block until <code>buffer.length</code> number of bytes
195: * have been read.
196: *
197: * @param buffer
198: * to read bytes into
199: *
200: * @throws IOException
201: * If a problem occurs reading from this DataInputStream.
202: *
203: * @see DataOutput#write(byte[])
204: * @see DataOutput#write(byte[], int, int)
205: */
206: public final void readFully(byte[] buffer) throws IOException {
207: readFully(buffer, 0, buffer.length);
208: }
209:
210: /**
211: * Reads bytes from this stream and stores them in the byte array
212: * <code>buffer</code> starting at the position <code>offset</code>.
213: * This method blocks until <code>count</code> bytes have been read.
214: *
215: * @param buffer
216: * the byte array into which the data is read
217: * @param offset
218: * the offset the operation start at
219: * @param length
220: * the maximum number of bytes to read
221: *
222: * @throws IOException
223: * if a problem occurs while reading from this stream
224: * @throws EOFException
225: * if reaches the end of the stream before enough bytes have
226: * been read
227: * @see java.io.DataInput#readFully(byte[], int, int)
228: */
229: public final void readFully(byte[] buffer, int offset, int length)
230: throws IOException {
231: if (length < 0) {
232: throw new IndexOutOfBoundsException();
233: }
234: if (length == 0) {
235: return;
236: }
237: if (in == null) {
238: throw new NullPointerException(Msg.getString("KA00b")); //$NON-NLS-1$
239: }
240: if (buffer == null) {
241: throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
242: }
243: if (offset < 0 || offset > buffer.length - length) {
244: throw new IndexOutOfBoundsException();
245: }
246: while (length > 0) {
247: int result = in.read(buffer, offset, length);
248: if (result < 0) {
249: throw new EOFException();
250: }
251: offset += result;
252: length -= result;
253: }
254: }
255:
256: /**
257: * Reads a 32-bit integer value from this stream.
258: *
259: * @return the next <code>int</code> value from the source stream.
260: *
261: * @throws IOException
262: * If a problem occurs reading from this DataInputStream.
263: *
264: * @see DataOutput#writeInt(int)
265: */
266: public final int readInt() throws IOException {
267: if (readToBuff(4) < 0) {
268: throw new EOFException();
269: }
270: return ((buff[0] & 0xff) << 24) | ((buff[1] & 0xff) << 16)
271: | ((buff[2] & 0xff) << 8) | (buff[3] & 0xff);
272: }
273:
274: /**
275: * Answers a <code>String</code> representing the next line of text
276: * available in this BufferedReader. A line is represented by 0 or more
277: * characters followed by <code>'\n'</code>, <code>'\r'</code>,
278: * <code>"\n\r"</code> or end of stream. The <code>String</code> does
279: * not include the newline sequence.
280: *
281: * @return the contents of the line or null if no characters were read
282: * before end of stream.
283: *
284: * @throws IOException
285: * If the DataInputStream is already closed or some other IO
286: * error occurs.
287: *
288: * @deprecated Use BufferedReader
289: */
290: @Deprecated
291: public final String readLine() throws IOException {
292: StringBuffer line = new StringBuffer(80); // Typical line length
293: boolean foundTerminator = false;
294: while (true) {
295: int nextByte = in.read();
296: switch (nextByte) {
297: case -1:
298: if (line.length() == 0 && !foundTerminator) {
299: return null;
300: }
301: return line.toString();
302: case (byte) '\r':
303: if (foundTerminator) {
304: ((PushbackInputStream) in).unread(nextByte);
305: return line.toString();
306: }
307: foundTerminator = true;
308: /* Have to be able to peek ahead one byte */
309: if (!(in.getClass() == PushbackInputStream.class)) {
310: in = new PushbackInputStream(in);
311: }
312: break;
313: case (byte) '\n':
314: return line.toString();
315: default:
316: if (foundTerminator) {
317: ((PushbackInputStream) in).unread(nextByte);
318: return line.toString();
319: }
320: line.append((char) nextByte);
321: }
322: }
323: }
324:
325: /**
326: * Reads a 64-bit <code>long</code> value from this stream.
327: *
328: * @return the next <code>long</code> value from the source stream.
329: *
330: * @throws IOException
331: * If a problem occurs reading from this DataInputStream.
332: *
333: * @see DataOutput#writeLong(long)
334: */
335: public final long readLong() throws IOException {
336: if (readToBuff(8) < 0) {
337: throw new EOFException();
338: }
339: int i1 = ((buff[0] & 0xff) << 24) | ((buff[1] & 0xff) << 16)
340: | ((buff[2] & 0xff) << 8) | (buff[3] & 0xff);
341: int i2 = ((buff[4] & 0xff) << 24) | ((buff[5] & 0xff) << 16)
342: | ((buff[6] & 0xff) << 8) | (buff[7] & 0xff);
343:
344: return ((i1 & 0xffffffffL) << 32) | (i2 & 0xffffffffL);
345: }
346:
347: /**
348: * Reads a 16-bit <code>short</code> value from this stream.
349: *
350: * @return the next <code>short</code> value from the source stream.
351: *
352: * @throws IOException
353: * If a problem occurs reading from this DataInputStream.
354: *
355: * @see DataOutput#writeShort(int)
356: */
357: public final short readShort() throws IOException {
358: if (readToBuff(2) < 0) {
359: throw new EOFException();
360: }
361: return (short) (((buff[0] & 0xff) << 8) | (buff[1] & 0xff));
362: }
363:
364: /**
365: * Reads an unsigned 8-bit <code>byte</code> value from this stream and
366: * returns it as an int.
367: *
368: * @return the next unsigned byte value from the source stream.
369: *
370: * @throws IOException
371: * If a problem occurs reading from this DataInputStream.
372: *
373: * @see DataOutput#writeByte(int)
374: */
375: public final int readUnsignedByte() throws IOException {
376: int temp = in.read();
377: if (temp < 0) {
378: throw new EOFException();
379: }
380: return temp;
381: }
382:
383: /**
384: * Reads a 16-bit unsigned <code>short</code> value from this stream and
385: * returns it as an int.
386: *
387: * @return the next unsigned <code>short</code> value from the source
388: * stream.
389: *
390: * @throws IOException
391: * If a problem occurs reading from this DataInputStream.
392: *
393: * @see DataOutput#writeShort(int)
394: */
395: public final int readUnsignedShort() throws IOException {
396: if (readToBuff(2) < 0) {
397: throw new EOFException();
398: }
399: return (char) (((buff[0] & 0xff) << 8) | (buff[1] & 0xff));
400: }
401:
402: /**
403: * Reads a UTF format String from this Stream.
404: *
405: * @return the next UTF String from the source stream.
406: *
407: * @throws IOException
408: * If a problem occurs reading from this DataInputStream.
409: *
410: * @see DataOutput#writeUTF(java.lang.String)
411: */
412: public final String readUTF() throws IOException {
413: return decodeUTF(readUnsignedShort());
414: }
415:
416: String decodeUTF(int utfSize) throws IOException {
417: return decodeUTF(utfSize, this );
418: }
419:
420: private static String decodeUTF(int utfSize, DataInput in)
421: throws IOException {
422: byte[] buf = new byte[utfSize];
423: char[] out = new char[utfSize];
424: in.readFully(buf, 0, utfSize);
425:
426: return Util.convertUTF8WithBuf(buf, out, 0, utfSize);
427: }
428:
429: /**
430: * Reads a UTF format String from the DataInput Stream <code>in</code>.
431: *
432: * @param in
433: * the input stream to read from
434: * @return the next UTF String from the source stream.
435: *
436: * @throws IOException
437: * If a problem occurs reading from this DataInputStream.
438: *
439: * @see DataOutput#writeUTF(java.lang.String)
440: */
441: public static final String readUTF(DataInput in) throws IOException {
442: return decodeUTF(in.readUnsignedShort(), in);
443: }
444:
445: /**
446: * Skips <code>count</code> number of bytes in this stream. Subsequent
447: * <code>read()</code>'s will not return these bytes unless
448: * <code>reset()</code> is used.
449: *
450: * @param count
451: * the number of bytes to skip.
452: * @return the number of bytes actually skipped.
453: *
454: * @throws IOException
455: * If the stream is already closed or another IOException
456: * occurs.
457: */
458: public final int skipBytes(int count) throws IOException {
459: int skipped = 0;
460: long skip;
461: while (skipped < count
462: && (skip = in.skip(count - skipped)) != 0) {
463: skipped += skip;
464: }
465: if (skipped < 0) {
466: throw new EOFException();
467: }
468: return skipped;
469: }
470: }
|