1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package java.io; 19 20import java.nio.ByteOrder; 21import java.nio.charset.ModifiedUtf8; 22import libcore.io.Memory; 23import libcore.io.Streams; 24import libcore.io.SizeOf; 25 26/** 27 * Wraps an existing {@link InputStream} and reads big-endian typed data from it. 28 * Typically, this stream has been written by a DataOutputStream. Types that can 29 * be read include byte, 16-bit short, 32-bit int, 32-bit float, 64-bit long, 30 * 64-bit double, byte strings, and strings encoded in 31 * {@link DataInput modified UTF-8}. 32 * 33 * @see DataOutputStream 34 */ 35public class DataInputStream extends FilterInputStream implements DataInput { 36 37 private final byte[] scratch = new byte[8]; 38 39 /** 40 * Constructs a new DataInputStream on the InputStream {@code in}. All 41 * reads are then filtered through this stream. Note that data read by this 42 * stream is not in a human readable format and was most likely created by a 43 * DataOutputStream. 44 * 45 * <p><strong>Warning:</strong> passing a null source creates an invalid 46 * {@code DataInputStream}. All operations on such a stream will fail. 47 * 48 * @param in 49 * the source InputStream the filter reads from. 50 * @see DataOutputStream 51 * @see RandomAccessFile 52 */ 53 public DataInputStream(InputStream in) { 54 super(in); 55 } 56 57 // overridden to add 'final' 58 @Override public final int read(byte[] buffer) throws IOException { 59 return super.read(buffer); 60 } 61 62 /** 63 * Reads at most {@code length} bytes from this stream and stores them in 64 * the byte array {@code buffer} starting at {@code offset}. Returns the 65 * number of bytes that have been read or -1 if no bytes have been read and 66 * the end of the stream has been reached. 67 * 68 * @param buffer 69 * the byte array in which to store the bytes read. 70 * @param offset 71 * the initial position in {@code buffer} to store the bytes 72 * read from this stream. 73 * @param length 74 * the maximum number of bytes to store in {@code buffer}. 75 * @return the number of bytes that have been read or -1 if the end of the 76 * stream has been reached. 77 * @throws IOException 78 * if a problem occurs while reading from this stream. 79 * @see DataOutput#write(byte[]) 80 * @see DataOutput#write(byte[], int, int) 81 */ 82 @Override 83 public final int read(byte[] buffer, int offset, int length) throws IOException { 84 return in.read(buffer, offset, length); 85 } 86 87 public final boolean readBoolean() throws IOException { 88 int temp = in.read(); 89 if (temp < 0) { 90 throw new EOFException(); 91 } 92 return temp != 0; 93 } 94 95 public final byte readByte() throws IOException { 96 int temp = in.read(); 97 if (temp < 0) { 98 throw new EOFException(); 99 } 100 return (byte) temp; 101 } 102 103 public final char readChar() throws IOException { 104 return (char) readShort(); 105 } 106 107 public final double readDouble() throws IOException { 108 return Double.longBitsToDouble(readLong()); 109 } 110 111 public final float readFloat() throws IOException { 112 return Float.intBitsToFloat(readInt()); 113 } 114 115 public final void readFully(byte[] dst) throws IOException { 116 readFully(dst, 0, dst.length); 117 } 118 119 public final void readFully(byte[] dst, int offset, int byteCount) throws IOException { 120 Streams.readFully(in, dst, offset, byteCount); 121 } 122 123 public final int readInt() throws IOException { 124 Streams.readFully(in, scratch, 0, SizeOf.INT); 125 return Memory.peekInt(scratch, 0, ByteOrder.BIG_ENDIAN); 126 } 127 128 @Deprecated 129 public final String readLine() throws IOException { 130 StringBuilder line = new StringBuilder(80); // Typical line length 131 boolean foundTerminator = false; 132 while (true) { 133 int nextByte = in.read(); 134 switch (nextByte) { 135 case -1: 136 if (line.length() == 0 && !foundTerminator) { 137 return null; 138 } 139 return line.toString(); 140 case (byte) '\r': 141 if (foundTerminator) { 142 ((PushbackInputStream) in).unread(nextByte); 143 return line.toString(); 144 } 145 foundTerminator = true; 146 /* Have to be able to peek ahead one byte */ 147 if (!(in.getClass() == PushbackInputStream.class)) { 148 in = new PushbackInputStream(in); 149 } 150 break; 151 case (byte) '\n': 152 return line.toString(); 153 default: 154 if (foundTerminator) { 155 ((PushbackInputStream) in).unread(nextByte); 156 return line.toString(); 157 } 158 line.append((char) nextByte); 159 } 160 } 161 } 162 163 public final long readLong() throws IOException { 164 Streams.readFully(in, scratch, 0, SizeOf.LONG); 165 return Memory.peekLong(scratch, 0, ByteOrder.BIG_ENDIAN); 166 } 167 168 public final short readShort() throws IOException { 169 Streams.readFully(in, scratch, 0, SizeOf.SHORT); 170 return Memory.peekShort(scratch, 0, ByteOrder.BIG_ENDIAN); 171 } 172 173 public final int readUnsignedByte() throws IOException { 174 int temp = in.read(); 175 if (temp < 0) { 176 throw new EOFException(); 177 } 178 return temp; 179 } 180 181 public final int readUnsignedShort() throws IOException { 182 return ((int) readShort()) & 0xffff; 183 } 184 185 public final String readUTF() throws IOException { 186 return decodeUTF(readUnsignedShort()); 187 } 188 189 String decodeUTF(int utfSize) throws IOException { 190 return decodeUTF(utfSize, this); 191 } 192 193 private static String decodeUTF(int utfSize, DataInput in) throws IOException { 194 byte[] buf = new byte[utfSize]; 195 in.readFully(buf, 0, utfSize); 196 return ModifiedUtf8.decode(buf, new char[utfSize], 0, utfSize); 197 } 198 199 public static final String readUTF(DataInput in) throws IOException { 200 return decodeUTF(in.readUnsignedShort(), in); 201 } 202 203 /** 204 * Skips {@code count} number of bytes in this stream. Subsequent {@code 205 * read()}s will not return these bytes unless {@code reset()} is used. 206 * 207 * This method will not throw an {@link EOFException} if the end of the 208 * input is reached before {@code count} bytes where skipped. 209 * 210 * @param count 211 * the number of bytes to skip. 212 * @return the number of bytes actually skipped. 213 * @throws IOException 214 * if a problem occurs during skipping. 215 * @see #mark(int) 216 * @see #reset() 217 */ 218 public final int skipBytes(int count) throws IOException { 219 int skipped = 0; 220 long skip; 221 while (skipped < count && (skip = in.skip(count - skipped)) != 0) { 222 skipped += skip; 223 } 224 return skipped; 225 } 226} 227