该类没有引入外界包
继承了FilterInputStream
完成了上篇文章所讲到的DataInput接口
类头注释
/** * A data input stream lets an application read primitive Java data * types from an underlying input stream in a machine-independent * way. An application uses a data output stream to write data that * can later be read by a data input stream. * <p> * DataInputStream is not necessarily safe for multithreaded access. * Thread safety is optional and is the responsibility of users of * methods in this class. * * @author Arthur van Hoff * @see java.io.DataOutputStream * @since JDK1.0 */
大意如下:
该类是一个数据输入流,可以让应用从底层输入流中读取Java基础数据类型且该方法与机器无关
一个应用使用数据输出流写出的数据稍后可以由数据输入流读取
DataInputStream对于多线程访问是不保证安全的
线程安全可选,但由该类方法的使用者负责
该类含有的成员变量:
readUTF中Byte缓冲
private byte bytearr[] = new byte[80];
readUTF中Char缓冲
private char chararr[] = new char[80];
readlong专用缓冲
private byte readBuffer[] = new byte[8];
该类含有的方法:
构造方法,简单调用父类构造方法
public DataInputStream(InputStream in) { super(in); }
从输入流中读取byte数据(尝试读满缓冲,返回实际读取长度)
public final int read(byte b[]) throws IOException { return in.read(b, 0, b.length); }
从输入流中读取byte数据(尝试向缓冲区特定位置读取特定长度数据)
public final int read(byte b[], int off, int len) throws IOException { return in.read(b, off, len); }
从输入流中读取byte数据(强制读满,未读满会抛出各种事件)
public final void readFully(byte b[]) throws IOException { readFully(b, 0, b.length); }
从输入流中读取byte数据(强制向缓冲区特定位置读取特定长度数据)
public final void readFully(byte b[], int off, int len) throws IOException { if (len < 0) throw new IndexOutOfBoundsException(); int n = 0; while (n < len) {//读取够量或者文件结束 int count = in.read(b, off + n, len - n); if (count < 0) throw new EOFException(); n += count; } }
跳过输入流后续的n个字符,返回实际跳过的字符数
public final int skipBytes(int n) throws IOException { int total = 0;//跳过字符记录 int cur = 0;//记录底层流每次实际跳过字符 while ((total<n) && ((cur = (int) in.skip(n-total)) > 0)) { total += cur; } return total; }
判定读取字符是否为0(一般编码中0对应空,如ascii)
public final boolean readBoolean() throws IOException { int ch = in.read();//读取下一个字节并返回int值(将二进制码转化为十进制) if (ch < 0) throw new EOFException(); return (ch != 0); }
读取一个byte数据,返回有符号8位值(二进制码,首位符号位)
public final byte readByte() throws IOException { int ch = in.read(); if (ch < 0) throw new EOFException(); return (byte)(ch); }
读取一个byte数据,返回无符号8位值(int型)
public final int readUnsignedByte() throws IOException { int ch = in.read(); if (ch < 0) throw new EOFException(); return ch; }
读取两个byte字节通过移位和强制类型转换返回short
public final short readShort() throws IOException { int ch1 = in.read(); int ch2 = in.read(); if ((ch1 | ch2) < 0) throw new EOFException(); return (short)((ch1 << 8) + (ch2 << 0)); }
返回无符号16位(把符号为也化成数值位)
public final int readUnsignedShort() throws IOException { int ch1 = in.read(); int ch2 = in.read(); if ((ch1 | ch2) < 0) throw new EOFException(); return (ch1 << 8) + (ch2 << 0); }
读取两个字节返回char
public final char readChar() throws IOException { int ch1 = in.read(); int ch2 = in.read(); if ((ch1 | ch2) < 0) throw new EOFException(); return (char)((ch1 << 8) + (ch2 << 0)); }
读取四个字节返回int值
public final int readInt() throws IOException { int ch1 = in.read(); int ch2 = in.read(); int ch3 = in.read(); int ch4 = in.read(); if ((ch1 | ch2 | ch3 | ch4) < 0) throw new EOFException(); return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0)); }
读取8个字节返回long值
public final long readLong() throws IOException { readFully(readBuffer, 0, 8); return (((long)readBuffer[0] << 56) +//位数较大时需先转化为long型,否则无法准确储存移位后数据(java中整数默认为int) ((long)(readBuffer[1] & 255) << 48) + ((long)(readBuffer[2] & 255) << 40) + ((long)(readBuffer[3] & 255) << 32) + ((long)(readBuffer[4] & 255) << 24) + ((readBuffer[5] & 255) << 16) + ((readBuffer[6] & 255) << 8) + ((readBuffer[7] & 255) << 0)); }
读取四个字节返回float
public final float readFloat() throws IOException { return Float.intBitsToFloat(readInt());//先化为int }
读取8个字节化为double
public final double readDouble() throws IOException { return Double.longBitsToDouble(readLong());//先化为long }
读取单行文本返回字符串
public final String readLine() throws IOException { char buf[] = lineBuffer;//读取缓冲区 if (buf == null) { buf = lineBuffer = new char[128];//初始化缓冲区 } int room = buf.length;//剩余可用空间 int offset = 0;//读取指针 int c; loop: while (true) { switch (c = in.read()) { case -1: case '\n'://新行符 break loop; case '\r': int c2 = in.read(); if ((c2 != '\n') && (c2 != -1)) {//c2不为换行符且c2读取成功 if (!(in instanceof PushbackInputStream)) {//进行类型检查,判断传入的该InputStream类是否是PushbackInputStream或者其子类 this.in = new PushbackInputStream(in); } ((PushbackInputStream)in).unread(c2);//将c2回退到缓冲区前面 } break loop; default: if (--room < 0) {//room大小非正 buf = new char[offset + 128];//生成新缓冲区 room = buf.length - offset - 1; System.arraycopy(lineBuffer, 0, buf, 0, offset); lineBuffer = buf; } buf[offset++] = (char) c; break; } } if ((c == -1) && (offset == 0)) { return null; } return String.copyValueOf(buf, 0, offset); }
默认读本类字符(改版UTF-8),返回字符串
public final String readUTF() throws IOException { return readUTF(this); }
读取特定DataInput的字符(改版UTF-8),返回字符串
public final static String readUTF(DataInput in) throws IOException { int utflen = in.readUnsignedShort();//utf长度 byte[] bytearr = null; char[] chararr = null; if (in instanceof DataInputStream) {//检查传入类是否为本类 DataInputStream dis = (DataInputStream)in; if (dis.bytearr.length < utflen){ dis.bytearr = new byte[utflen*2];//初始化缓冲区 dis.chararr = new char[utflen*2]; } chararr = dis.chararr;//绑定 bytearr = dis.bytearr; } else { bytearr = new byte[utflen];//直接初始化 chararr = new char[utflen]; } int c, char2, char3; int count = 0;//共读取长度 int chararr_count=0; in.readFully(bytearr, 0, utflen);//填充byte缓冲 while (count < utflen) { c = (int) bytearr[count] & 0xff; if (c > 127) break; count++; chararr[chararr_count++]=(char)c; } while (count < utflen) { c = (int) bytearr[count] & 0xff; switch (c >> 4) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: /* 0xxxxxxx*/ count++; chararr[chararr_count++]=(char)c; break; case 12: case 13: /* 110x xxxx 10xx xxxx*/ count += 2; if (count > utflen) throw new UTFDataFormatException( "malformed input: partial character at end"); char2 = (int) bytearr[count-1]; if ((char2 & 0xC0) != 0x80) throw new UTFDataFormatException( "malformed input around byte " + count); chararr[chararr_count++]=(char)(((c & 0x1F) << 6) | (char2 & 0x3F)); break; case 14: /* 1110 xxxx 10xx xxxx 10xx xxxx */ count += 3; if (count > utflen) throw new UTFDataFormatException( "malformed input: partial character at end"); char2 = (int) bytearr[count-2]; char3 = (int) bytearr[count-1]; if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80)) throw new UTFDataFormatException( "malformed input around byte " + (count-1)); chararr[chararr_count++]=(char)(((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)); break; default: /* 10xx xxxx, 1111 xxxx */ throw new UTFDataFormatException( "malformed input around byte " + count); } } // The number of chars produced may be less than utflen return new String(chararr, 0, chararr_count); }
DataInputStream类的设计思路应该是:想要设计一个有这些功能的类,但Java不支持多重继承,所以把该类做成了一个接口(DataInput),同时DataInputStream就是该类实例化的体现之一。该类的代码除了readUTF()稍微复杂一些,其他都是十分基础和简单的,只是对各数据类型的空间占用有所涉及。