今天在学习Java的IO操作中遇到一个百思不得其解的问题,下面的代码是今天做的关于DataInputStream类的练习,我很不解为什么DataInputStream的readUTF方法不需要任何参数,但是却在读取的时候可以知道自己读取多长,不明白他是怎么知道我当初在写入的时候写入的长度的,他是靠什么控制读取的范围的呀???比如下面的程序,readUTF方法就可以知道读取"昨天"这两个字,是怎么知道我就刚好需要读这两个字,而不会把下面的内容给读出。很是感谢大家的回答
package com.zhang.hello; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class IODataStreamTest { public static void main(String[] args) throws IOException { File file=new File("f:/zhang.dat"); if(!file.exists()){ file.createNewFile(); } DataInputStream dis=new DataInputStream(new FileInputStream(file)); DataOutputStream dos=new DataOutputStream(new FileOutputStream(file)); int testInt=2016; double testDouble=10.12; long testLong=20161012; dos.writeInt(testInt); dos.writeDouble(testDouble); dos.writeLong(testLong); //utf-8 一个中文占3个字节 dos.writeUTF("昨天"); dos.writeUTF("今天是个好日子"); dos.close(); int testRInt=dis.readInt(); System.out.println(testRInt); double testRDouble=dis.readDouble(); System.out.println(testRDouble); long testRLong=dis.readLong(); System.out.println(testRLong); String testRStr=dis.readUTF();//为什么readUTF知道读取多长 System.out.println(testRStr); dis.close(); } }
执行结果:
2016
10.12
20161012
昨天
三叔2016-10-27 11:19:04
DataOutputStream
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= 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); // 写入的长度在字符串中增加了2,即字节长度标识所占用的资源 return utflen + 2; }
DataInputStream
public final static String readUTF(DataInput in) throws IOException { // 读取字符串字节长度 int utflen = in.readUnsignedShort(); //... }
实际上在调用writeUTF写入时jdk内部有将字符串的字节数写入流中,读取时先读取到字节长度,按照指定的字节长度读取出相应的字符串。