关于
java.io.DataInputStream
和
java.io.DataOutputStream
的部分笔记,这两个类共同实现对数据类型为Java原生数据类型的数据的字节输入、输出流操作。本文演示代码段的执行环境基于JDK版本
1.7
。
1 2 3 4 5 6 7 8 9 10 11
--java.lang.Object --java.io.InputStream --java.io.FilterInputStream --java.io.DataInputStream --java.lang.Object --java.io.OutputStream --java.io.FilterOutputStream --java.io.DataOutputStream
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
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; } } public final void readFully (byte b[]) throws IOException { readFully(b, 0 , b.length); }
1 2 3 4 5 6 7 8 9 10
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; }
1 2 3 4 5 6 7
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 )); }
1 2 3 4 5 6 7
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 ); }
1 2 3 4 5 6 7 8 9 10 11
public final long readLong () throws IOException { readFully(readBuffer, 0 , 8 ); return (((long )readBuffer[0 ] << 56 ) + ((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 )); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
public final static String readUTF (DataInput in) throws IOException { int utflen = in.readUnsignedShort(); 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); 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 : count++; chararr[chararr_count++]=(char )c; break ; case 12 : case 13 : 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 : 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 : throw new UTFDataFormatException( "malformed input around byte " + count); } } return new String(chararr, 0 , chararr_count); }
1 2 3 4 5 6 7
private void incCount (int value) { int temp = written + value; if (temp < 0 ) { temp = Integer.MAX_VALUE; } written = temp; }
1 2 3 4 5 6 7 8 9 10
public synchronized void write (int b) throws IOException { out.write(b); incCount(1 ); } public synchronized void write (byte b[], int off, int len) throws IOException { out.write(b, off, len); incCount(len); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
public final void writeBoolean (boolean v) throws IOException { out.write(v ? 1 : 0 ); incCount(1 ); } public final void writeByte (int v) throws IOException { out.write(v); incCount(1 ); } public final void writeShort (int v) throws IOException { out.write((v >>> 8 ) & 0xFF ); out.write((v >>> 0 ) & 0xFF ); incCount(2 ); } public final void writeChar (int v) throws IOException { out.write((v >>> 8 ) & 0xFF ); out.write((v >>> 0 ) & 0xFF ); incCount(2 ); } public final void writeInt (int v) throws IOException { out.write((v >>> 24 ) & 0xFF ); out.write((v >>> 16 ) & 0xFF ); out.write((v >>> 8 ) & 0xFF ); out.write((v >>> 0 ) & 0xFF ); incCount(4 ); } public final void writeLong (long v) throws IOException { writeBuffer[0 ] = (byte )(v >>> 56 ); writeBuffer[1 ] = (byte )(v >>> 48 ); writeBuffer[2 ] = (byte )(v >>> 40 ); writeBuffer[3 ] = (byte )(v >>> 32 ); writeBuffer[4 ] = (byte )(v >>> 24 ); writeBuffer[5 ] = (byte )(v >>> 16 ); writeBuffer[6 ] = (byte )(v >>> 8 ); writeBuffer[7 ] = (byte )(v >>> 0 ); out.write(writeBuffer, 0 , 8 ); incCount(8 ); } public final void writeFloat (float v) throws IOException { writeInt(Float.floatToIntBits(v)); } public final void writeDouble (double v) throws IOException { writeLong(Double.doubleToLongBits(v)); }
1 2 3 4 5 6 7
public final void writeBytes (String s) throws IOException { int len = s.length(); for (int i = 0 ; i < len ; i++) { out.write((byte )s.charAt(i)); } incCount(len); }
1 2 3 4 5 6 7 8 9
public final void writeChars (String s) throws IOException { int len = s.length(); for (int i = 0 ; i < len ; i++) { int v = s.charAt(i); out.write((v >>> 8 ) & 0xFF ); out.write((v >>> 0 ) & 0xFF ); } incCount(len * 2 ); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
static int writeUTF (String str, DataOutput out) throws IOException { int strlen = str.length(); int utflen = 0 ; int c, count = 0 ; for (int i = 0 ; i < strlen; i++) { c = str.charAt(i); if ((c >= 0x0001 ) && (c <= 0x007F )) { utflen++; } else if (c > 0x07FF ) { utflen += 3 ; } else { utflen += 2 ; } } if (utflen > 65535 ) throw new UTFDataFormatException( "encoded string too long: " + utflen + " bytes" ); byte [] bytearr = null ; if (out instanceof DataOutputStream) { DataOutputStream dos = (DataOutputStream)out; if (dos.bytearr == null || (dos.bytearr.length < (utflen+2 ))) dos.bytearr = new byte [(utflen*2 ) + 2 ]; bytearr = dos.bytearr; } else { bytearr = new byte [utflen+2 ]; } bytearr[count++] = (byte ) ((utflen >>> 8 ) & 0xFF ); bytearr[count++] = (byte ) ((utflen >>> 0 ) & 0xFF ); int i=0 ; for (i=0 ; i<strlen; i++) { c = str.charAt(i); if (!((c >= 0x0001 ) && (c <= 0x007F ))) break ; bytearr[count++] = (byte ) c; } for (;i < strlen; i++){ c = str.charAt(i); if ((c >= 0x0001 ) && (c <= 0x007F )) { bytearr[count++] = (byte ) c; } else if (c > 0x07FF ) { bytearr[count++] = (byte ) (0xE0 | ((c >> 12 ) & 0x0F )); bytearr[count++] = (byte ) (0x80 | ((c >> 6 ) & 0x3F )); bytearr[count++] = (byte ) (0x80 | ((c >> 0 ) & 0x3F )); } else { bytearr[count++] = (byte ) (0xC0 | ((c >> 6 ) & 0x1F )); bytearr[count++] = (byte ) (0x80 | ((c >> 0 ) & 0x3F )); } } out.write(bytearr, 0 , utflen+2 ); return utflen + 2 ; }
1 2 3
public final int size () { return written; }
码点范围 (十六进制)
UTF-8 (二进制)
注释
000000 - 00007F
0zzzzzzz
ASCII字符范围,字节由零开始
000080 - 0007FF
110yyyyy 10zzzzzz
第一个字节由110开始,接着的字节由10开始
000800 - 00D7FF
00E000 - 00FFFF
1110xxxx 10yyyyyy 10zzzzzz
第一个字节由1110开始,接着的字节由10开始
010000 - 10FFFF
11110www 10xxxxxx 10yyyyyy 10zzzzzz
将由11110开始,接着的字节由10开始
Stack Overflow.
DataInputStream.read() vs DataInputStream.readFully()
[E]