RandomAccessFile 的意外输出

Unexpected output with RandomAccessFile

我正在尝试了解 RandomAccessFile,但在创建测试程序后我得到了一些奇怪的输出。

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

public class RandomAccessFileTest
{
    public static void main(String[] args) throws IOException
    {
        // Create a new blank file
        File file = new File("RandomAccessFileTest.txt");
        file.createNewFile();
        
        // Open the file in read/write mode
        RandomAccessFile randomfile = new RandomAccessFile(file, "rw");
        
        // Write stuff
        randomfile.write("Hello World".getBytes());
        
        // Go to a location
        randomfile.seek(0);
        
        // Get the pointer to that location
        long pointer = randomfile.getFilePointer();
        System.out.println("location: " + pointer);
        
        // Read a char (two bytes?)
        char letter = randomfile.readChar();
        System.out.println("character: " + letter);
        
        randomfile.close();
    }
}

这个程序打印出来

location: 0

character: ?

原来字母的值是'䡥',而它应该是'H'。

我发现了一个类似的问题,显然这是由读取一个字节而不是两个字节引起的,但它没有解释具体如何解决它。

您已经用平台默认编码编写了 "Hello World" - 这很可能每个字符使用一个字节。

然后您正在读取 RandomAccessFile.readChar,它总是读取两个字节。文档:

Reads a character from this file. This method reads two bytes from the file, starting at the current file pointer. If the bytes read, in order, are b1 and b2, where 0 <= b1, b2 <= 255, then the result is equal to:

   (char)((b1 << 8) | b2)

This method blocks until the two bytes are read, the end of the stream is detected, or an exception is thrown.

所以 He 被组合成一个字符 - H 是 U+0048,e 是 U+0065,所以假设他们已经被写成 ASCII 字符,你正在读取字节 0x48 和 0x65 并将它们组合成 U+4865 这是 "a moving cart".

的汉字

基本上,您不应该使用 readChar 来尝试读取此数据。

通常要读取文本文件,您需要 InputStreamReader(具有适当的编码)包装 InputStream(例如 FileInputStream)。尝试使用 RandomAccessFile 执行此操作并不理想 - 您 可以 将数据读入 byte[] 然后将其转换为 String 但是是你需要考虑的各种微妙之处。