Java - RandomAccessFile.writeChars、writeChar使字符串长度扩展一倍的原因分析


RandomAccessFile是一个随机读写流。

    今天在使用该流写入数据时,发现写入的数据读出来之后与源数据比较,结果是不相等。代码如下:

while((s=rw.readLine())!=null){
       System.out.println("s:"+s);
    System.out.print("s:长度"+s.length()+"\n");
       String[] record=s.split(",");
    System.out.print("record[0]:长度"+record[0].length()+"\n");
    System.out.print("record[1]:长度"+record[1].length()+"\n");
    System.out.print("record[2]:长度"+record[2].length()+"\n");

       System.out.print("record[0]:按照长度打印"+record[0].length()+"\n");
       for(int ii=0;ii<record[0].length();ii++){
           System.out.print( record[0].charAt(ii));
       }

        System.out.println();
        System.out.println("record[0]:按照字符串"+record[0]);
        System.out.println(filename[filename.length-1]);

        System.out.println(record[0].compareTo(filename[filename.length-1])+" "+record[0]+" "+filename[filename.length-1]);

输出的结果如下:

我们发现读取的字符串s,内容为123456,0,1。但是长度却为21。

比较的两个字符串record[0]:123456,和filename[filename.length-1]:123456。比较的结果不为0


哈?!黑人问号,怎么回事呢?

经过代码分析,发现,问题是出在了rw.writeChars(str);

因为writeChars写入文件时,字符数据被分了两个字节。高位为0,低位才是有效数据。

String str =filename[filename.length-1]+","+err[1]+","+count+"\n";
rw.writeChars(str);

下面我们针对writeChars这函数进行测试:写入函数有:bufferedWriter.write(s[0]);randomAccessFile.writeChars(s[0]);

public class tex {
    public static void main(String[] args){
        String[] s="123,123456,123456789".split(",");
        System.out.println(s.length);
        System.out.println(s);
        System.out.println(s[0]+" "+s[0].length());
        System.out.println(s[1]+" "+s[1].length());
        System.out.println(s[2]+" "+s[2].length());
        File file =new File("text.txt");
        System.out.println(file.getAbsolutePath());
        try {
            FileWriter fileWriter=new FileWriter(file);
            BufferedWriter bufferedWriter =new BufferedWriter(fileWriter);
            System.out.println();
            System.out.println(s[0].length());
            bufferedWriter.write(s[0]);
            bufferedWriter.newLine();
            bufferedWriter.flush();
            bufferedWriter.close();
            fileWriter.close();

            FileReader fileReader=new FileReader(file);
            BufferedReader bufferedReader =new BufferedReader(fileReader);
            String str= bufferedReader.readLine();
            System.out.println(str.length());
            bufferedReader.close();
            fileReader.close();
        }catch (Exception e){
        }
        try {
            RandomAccessFile randomAccessFile =new RandomAccessFile( new File("ra.txt"),"rw");
            randomAccessFile.writeChars(s[0]);
            System.out.println(s[0].length());
            long p=0;
            randomAccessFile.seek(p);
            String str1=randomAccessFile.readLine();
            System.out.println(str1);
            System.out.println(str1.length());
        }catch (Exception e){
        }
    }
}

输出的结果如下:

我们可以发现,使用bufferedWriter.write(s[0])写入的数据,在读取之后的长度不变为3。

但是randomAccessFile.writeChars(s[0]);写入的数据,在读取之后的长度扩展为2倍为6;但输出显示依然是3个数据。


为了弄清楚为什么造成这两倍的差异,我们查看writeChars函数的实现

public final void writeChars(String s) throws IOException {
    int clen = s.length();
    int blen = 2*clen;
    byte[] b = new byte[blen];
    char[] c = new char[clen];
    s.getChars(0, clen, c, 0);
    for (int i = 0, j = 0; i < clen; i++) {
        b[j++] = (byte)(c[i] >>> 8);
        b[j++] = (byte)(c[i] >>> 0);
    }
    writeBytes(b, 0, blen);

可以直观的看到,byte[] b的长度是char[] c的两倍。所以才会遇到之前的长度为6,输出却只有三个字符。

writeChar和writeChars原理一样,只是参数是一个int型(char等可以转化为int的可是可行的)。


另外我们从文件中也能看出两者的区别。writeChars,字符之间是有空格的。

集成环境中的终端输出,复制出来重新粘贴,会发现字符之间也有空格。



总结,我们尽量使用有编码方式的写入( writeUTF、readUTF ),或者自己设置好编码方式。编码方式这里不详细说

猜你喜欢

转载自blog.csdn.net/m0_37128231/article/details/80819078