search

Home  >  Q&A  >  body text

Java的DataInputStream的readUTF方法是怎么读取字符串的???

今天在学习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
昨天

高洛峰高洛峰2942 days ago962

reply all(1)I'll reply

  • 三叔

    三叔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内部有将字符串的字节数写入流中,读取时先读取到字节长度,按照指定的字节长度读取出相应的字符串。

    reply
    0
  • Cancelreply