如何在Java NIO解码过程中消除错误符号?

如何在Java NIO解码过程中消除错误符号?,java,decode,nio,Java,Decode,Nio,我需要从文件中读取文本,例如,在控制台中打印它。该文件是UTF-8格式的。似乎我做错了什么,因为一些俄罗斯符号打印错误。我的代码怎么了 StringBuilder content = new StringBuilder(); try (FileChannel fChan = (FileChannel) Files.newByteChannel(Paths.get("D:/test.txt")) ) { ByteBuffer byte

我需要从文件中读取文本,例如,在控制台中打印它。该文件是UTF-8格式的。似乎我做错了什么,因为一些俄罗斯符号打印错误。我的代码怎么了

StringBuilder content = new StringBuilder();

        try (FileChannel fChan = (FileChannel) Files.newByteChannel(Paths.get("D:/test.txt")) ) {

            ByteBuffer byteBuf = ByteBuffer.allocate(16);
            Charset charset = Charset.forName("UTF-8");

            while(fChan.read(byteBuf) != -1) {
                byteBuf.flip();
                content.append(new String(byteBuf.array(), charset));
                byteBuf.clear();
            }

            System.out.println(content);
        } 
结果是:

Здравствуйте, как поживае��е?
Это п��имер текста на русском яз��ке.ом яз�
实际案文:

Здравствуйте, как поживаете?
Это пример текста на русском языке.

UTF-8使用每个字符的可变字节数。这给了您一个边界错误:您将基于缓冲区的代码与基于字节数组的代码混合在一起,而您不能在这里这样做;您可以读取足够多的字节,使其卡在字符的中间,然后将输入转换为字节数组,并将其转换,这将失败,因为您无法转换半个字符

您真正想要的是,要么先读取所有数据,然后转换整个输入,要么在倒转时保留bytebuffer中的任何半个字符,或者更好的是,放弃所有这些内容,使用为读取实际字符而编写的代码。一般来说,使用channel API会使事情复杂化很多;它是灵活的,但很复杂——这就是它的运作方式

除非你能解释你为什么需要它,否则不要使用它。改为这样做:

Path target = Paths.get("D:/test.txt");
try (var reader = Files.newBufferedReader(target)) {
    // read a line at a time here. Yes, it will be UTF-8 decoded.
}
或者更好,因为你显然想一次读完整件事:

Path target = Paths.get("D:/test.txt");
var content = Files.readString(target);

注意:与大多数将字节转换为字符或将字节转换为字符的java方法不同,
文件
API默认为UTF-8(而不是大多数java API所做的无用、危险、不稳定的导致“平台默认编码”的错误)。这就是为什么最后这段极其简单的代码仍然是正确的。

这种方法的一个问题可能是,将多个字节分隔开来,形成一个字符。但这通常发生在更大的规模上,即更大的缓冲区大小,如20KB及以上。这里的确切问题我还不清楚。最好是使用
文件.newbuffereder(path,Charset.forName(“UTF-8”))
或者干脆使用
文件.readAllLines(path)@JayC667,我认为,这是一个关于意外分割unicode符号的好假设。我改变了ByteBuffer的容量,结果变得正确了!如何使用
文件.行
?Unicode字符可能由多个字节组成。假设文件中的一个字符由3个字节组成。当缓冲区满时,通道只读取了该字符的2个字节。这意味着最后1个字节进入下一个缓冲区。而这个字符的编码将不正确<代码>文件.readAllLines(路径)是实现此类功能的良好选项。