特殊流(DataInputStream与DataOutputStream)分析
特殊流/数据流(DataInputStream与DataOutputStream)引用的是字节流,所以DataInputStream与DataOutputStream属于高级流。
DataInputStream
数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本Java数据类型。应用程序可以使用数据输出流写入稍后有数据输入流读取的数据。DateInputStream对于多线程访问不一定是安全的。线程安全是可选的,它由此类方法的使用者负责。
**
源码分析
**
继承关系
class DataInputStream extends FilterInputStream implements
第一种读取方式,无参
/**
/* int read() throws IOException {
return in.read()
/*读取第一个字节,返回值为int类型(使用FilterInputStream中的read()方法)
*/
System.out.println(dataInputStream.read());
第二种读取方式,参数为byte[]
/**
* final int read(byte b[]) throws IOException {
* return in.read(b, 0, b.length);
* }
* 返回值为int类型,返回结果为读取到的实际个数
*/
byte [] b=new byte[30];
System.out.println(dataInputStream.read(b));
System.out.println(Arrays.toString(b));
第三种读取方式,有参
/**
*final int read(byte b[], int off, int len) throws IOException {
* return in.read(b, off, len);
* 返回值:int类型,实际读取到的个数
* 参数:
* byte b[]:表示读取到的数据存储到该数组
* int off:表示从存储数组的偏移位置off开始存储字符
* int len:读取的数据的长度
*/
byte [] b=new byte[30];
System.out.println(dataInputStream.read(b,0,5));
System.out.println(Arrays.toString(b));
特有方法
readUTF读取由writeUTF修改的数据。
/**
* 特殊方法
* final String readUTF() throws IOException {
* return readUTF(this);
*/
System.out.println(dataInputStream.readUTF());
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:
/* 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);
}
}
其他方法
public abstract void readFully(byte abyte0[])
throws IOException;
public abstract void readFully(byte abyte0[], int i, int j)
throws IOException;
public abstract int skipBytes(int i)
throws IOException;
public abstract boolean readBoolean()
throws IOException;
public abstract byte readByte()
throws IOException;
public abstract int readUnsignedByte()
throws IOException;
public abstract short readShort()
throws IOException;
public abstract int readUnsignedShort()
throws IOException;
public abstract char readChar()
throws IOException;
public abstract int readInt()
throws IOException;
public abstract long readLong()
throws IOException;
public abstract float readFloat()
throws IOException;
public abstract double readDouble()
throws IOException;
DataOutputStream
源码分析
继承关系
class DataOutputStream extends FilterOutputStream implements DataOutput {
第一种写入方法,写入单个字节
/**
* synchronized void write(int b) throws IOException {
* out.write(b);
* incCount(1);
* 写入一个字节
*/
dataOutputStream.write(97);
第二种写入方法,写入
/**
* synchronized void write(byte b[], int off, int len)
* throws IOException
* {
* out.write(b, off, len);
* incCount(len);
* }
*/
byte[] b=new byte[]{97,98,99,103,113,107,100,112,108};
dataOutputStream.write(b,0,5);
第三种写入方法(特殊写入方法)
/**
* final void writeUTF(String str) throws IOException {
* writeUTF(str, this);
* }
*/
dataOutputStream.writeUTF("11.24你好tulun");
该写入方法写入的数据只能通过readUTF读取。
static int writeUTF(String str, DataOutput out) throws IOException {
int strlen = str.length();
int utflen = 0;
int c, count = 0;
/* use charAt instead of copying String to char array */
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;
}
其他方法:同DataInputStream拥有基本类型的 写入方法