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 @Override public final int read(byte[] buffer, int byteOffset, int byteCount) throws IOException { 63 return in.read(buffer, byteOffset, byteCount); 64 } 65 66 public final boolean readBoolean() throws IOException { 67 int temp = in.read(); 68 if (temp < 0) { 69 throw new EOFException(); 70 } 71 return temp != 0; 72 } 73 74 public final byte readByte() throws IOException { 75 int temp = in.read(); 76 if (temp < 0) { 77 throw new EOFException(); 78 } 79 return (byte) temp; 80 } 81 82 public final char readChar() throws IOException { 83 return (char) readShort(); 84 } 85 86 public final double readDouble() throws IOException { 87 return Double.longBitsToDouble(readLong()); 88 } 89 90 public final float readFloat() throws IOException { 91 return Float.intBitsToFloat(readInt()); 92 } 93 94 public final void readFully(byte[] dst) throws IOException { 95 readFully(dst, 0, dst.length); 96 } 97 98 public final void readFully(byte[] dst, int offset, int byteCount) throws IOException { 99 Streams.readFully(in, dst, offset, byteCount); 100 } 101 102 public final int readInt() throws IOException { 103 Streams.readFully(in, scratch, 0, SizeOf.INT); 104 return Memory.peekInt(scratch, 0, ByteOrder.BIG_ENDIAN); 105 } 106 107 /** 108 * @deprecated This method cannot be trusted to convert bytes to characters correctly. 109 * Wrap this stream with a {@link BufferedReader} instead. 110 */ 111 @Deprecated 112 public final String readLine() throws IOException { 113 StringBuilder line = new StringBuilder(80); // Typical line length 114 boolean foundTerminator = false; 115 while (true) { 116 int nextByte = in.read(); 117 switch (nextByte) { 118 case -1: 119 if (line.length() == 0 && !foundTerminator) { 120 return null; 121 } 122 return line.toString(); 123 case (byte) '\r': 124 if (foundTerminator) { 125 ((PushbackInputStream) in).unread(nextByte); 126 return line.toString(); 127 } 128 foundTerminator = true; 129 /* Have to be able to peek ahead one byte */ 130 if (!(in.getClass() == PushbackInputStream.class)) { 131 in = new PushbackInputStream(in); 132 } 133 break; 134 case (byte) '\n': 135 return line.toString(); 136 default: 137 if (foundTerminator) { 138 ((PushbackInputStream) in).unread(nextByte); 139 return line.toString(); 140 } 141 line.append((char) nextByte); 142 } 143 } 144 } 145 146 public final long readLong() throws IOException { 147 Streams.readFully(in, scratch, 0, SizeOf.LONG); 148 return Memory.peekLong(scratch, 0, ByteOrder.BIG_ENDIAN); 149 } 150 151 public final short readShort() throws IOException { 152 Streams.readFully(in, scratch, 0, SizeOf.SHORT); 153 return Memory.peekShort(scratch, 0, ByteOrder.BIG_ENDIAN); 154 } 155 156 public final int readUnsignedByte() throws IOException { 157 int temp = in.read(); 158 if (temp < 0) { 159 throw new EOFException(); 160 } 161 return temp; 162 } 163 164 public final int readUnsignedShort() throws IOException { 165 return ((int) readShort()) & 0xffff; 166 } 167 168 public final String readUTF() throws IOException { 169 return decodeUTF(readUnsignedShort()); 170 } 171 172 String decodeUTF(int utfSize) throws IOException { 173 return decodeUTF(utfSize, this); 174 } 175 176 private static String decodeUTF(int utfSize, DataInput in) throws IOException { 177 byte[] buf = new byte[utfSize]; 178 in.readFully(buf, 0, utfSize); 179 return ModifiedUtf8.decode(buf, new char[utfSize], 0, utfSize); 180 } 181 182 public static final String readUTF(DataInput in) throws IOException { 183 return decodeUTF(in.readUnsignedShort(), in); 184 } 185 186 /** 187 * Skips {@code count} number of bytes in this stream. Subsequent {@code 188 * read()}s will not return these bytes unless {@code reset()} is used. 189 * 190 * This method will not throw an {@link EOFException} if the end of the 191 * input is reached before {@code count} bytes where skipped. 192 * 193 * @param count 194 * the number of bytes to skip. 195 * @return the number of bytes actually skipped. 196 * @throws IOException 197 * if a problem occurs during skipping. 198 * @see #mark(int) 199 * @see #reset() 200 */ 201 public final int skipBytes(int count) throws IOException { 202 int skipped = 0; 203 long skip; 204 while (skipped < count && (skip = in.skip(count - skipped)) != 0) { 205 skipped += skip; 206 } 207 return skipped; 208 } 209} 210