Java Nio ByteBuffer 在缓冲区达到其边界时截断 unicode 字符

Java Nio ByteBuffer truncate unicode characters when buffer reaches its bound

我在 java 中编写了一个函数,它可以读取文件并将其内容获取到字符串:

public static String ReadFromFile(String fileLocation) {
    StringBuilder result = new StringBuilder();
    RandomAccessFile randomAccessFile = null;
    FileChannel fileChannel = null;
    try {
        randomAccessFile = new RandomAccessFile(fileLocation, "r");
        fileChannel = randomAccessFile.getChannel();
        ByteBuffer byteBuffer = ByteBuffer.allocate(10);
        CharBuffer charBuffer = null;
        int bytesRead = fileChannel.read(byteBuffer);
        while (bytesRead != -1) {
            byteBuffer.flip();
            charBuffer = StandardCharsets.UTF_8.decode(byteBuffer);
            result.append(charBuffer.toString());
            byteBuffer.clear();
            bytesRead = fileChannel.read(byteBuffer);
        }
    } catch (IOException ignored) {
    } finally {
        try {
            if (fileChannel != null)
                fileChannel.close();
            if (randomAccessFile != null)
                randomAccessFile.close();
        } catch (IOException ignored) {
        }
    }
    return result.toString();
}

从上面的代码可以看出,我故意将 'ByteBuffer.allocate' 设置为 10 个字节,以使事情更清楚。 现在我想读取一个名为“test.txt”的文件,其中包含这样的中文 unicode 字符:

乐正绫我爱你乐正绫我爱你

下面是我的测试代码:

System.out.println(ReadFromFile("test.txt"));

控制台中的预期输出

乐正绫我爱你乐正绫我爱你

控制台中的实际输出

乐正绫���爱你��正绫我爱你

可能原因
ByteBuffer 只分配了 10 个字节,因此 unicode 字符每 10 个字节被截断。

尝试解决
将 ByteBuffer 分配的字节数增加到 20,我得到以下结果:

乐正绫我爱你��正绫我爱你

不是一个可靠的解决方案
将ByteBuffer分配到一个非常大的数字,比如102400,但是对于非常大的文本文件来说并不实用。

问题
如何解决这个问题?

你不能,因为你不知道 UTF-8 编码中每个字符使用了多少字节,你真的不想重写那个逻辑。

Files.readString() in Java 11, for lower versions you can use Files.readAllBytes()例如

Path path = new File(fileLocation).toPath()
String contents = new String(Files.readAllBytes(path), StandardCharsets.UTF_8);