Java 俄罗斯字符

Java 俄罗斯字符,java,encoding,java-7,nio,cyrillic,Java,Encoding,Java 7,Nio,Cyrillic,最近我开始学习java.nio。在我的教科书中,我有一个例子,如何使用seekablebytechnel阅读文本文件: int count; Path path; try { path = Paths.get(System.getProperty("user.home") + "/desktop/text.txt"); } catch (InvalidPathException e) { out.println(e.getMessage()); return; } t

最近我开始学习java.nio。在我的教科书中,我有一个例子,如何使用seekablebytechnel阅读文本文件:

int count;
Path path;

try {
    path = Paths.get(System.getProperty("user.home") + "/desktop/text.txt");
} catch (InvalidPathException e) {
    out.println(e.getMessage());
    return;
}

try (SeekableByteChannel channel = Files.newByteChannel(path)) {
    ByteBuffer buffer = ByteBuffer.allocate(128);

    do {
        count = channel.read(buffer);

        if (count != -1) {
            buffer.rewind();
            for (int i = 0; i < count; i++)
                out.print((char) buffer.get());
        }
    } while (count != -1);

} catch (IOException e) {
    out.println("File not found!!!");
}

out.flush();
int计数;
路径;
试一试{
path=path.get(System.getProperty(“user.home”)+“/desktop/text.txt”);
}捕获(无效的异常e){
out.println(e.getMessage());
返回;
}
try(seekableytechnel=Files.newbytechnel(路径)){
ByteBuffer缓冲区=ByteBuffer.allocate(128);
做{
计数=通道读取(缓冲区);
如果(计数!=-1){
buffer.rewind();
for(int i=0;i
所以我用ANSI编码制作了一个包含英语和俄语单词的文本文件。这就是我得到的:

方法buffer.get()返回字节值,俄语字符从1000开始。因此,我将编码更改为UTF-8,并使用了另一种方法:

for (int i = 0; i < count; i += 2)
    out.print(buffer.getChar()); //reads 2 bytes and converts them to char
for(int i=0;i
但这给了我一个问号

那么,有人知道如何使用seekablebytechnel正确阅读俄语文本吗?

ByteBuffer的
方法
getChar()
读取两个字节,并将它们解释为
字符的高字节和低字节,换句话说,总是使用
UTF-16
编码。通常,您不应该尝试手动将字节拼凑到
String
s,而不是使用旧的I/O API和NIO。请注意,在尝试手动解码缓冲区中的字节时,需要处理的一件事是,对于多字节编码,缓冲区中的字节可能不会以字符边界结束

如果要从
seekablebytechnel
读取文本,可以使用来构造
读取器
,使用指定的字符集对字节进行解码

当然,您可以完全跳过
频道
的内容,并使用从
路径
创建一个
阅读器

顺便说一下,示例代码是有问题的,即使是读取字节序列。以下是一个简化的示例:

Path path=Paths.get(System.getProperty("user.home")).resolve("desktop/text.txt");
try(FileChannel channel=FileChannel.open(path)) {
  ByteBuffer buffer = ByteBuffer.allocate(128);
  while(channel.read(buffer)!=-1) {
    buffer.flip();
    while(buffer.hasRemaining())
        System.out.printf("%02x ", buffer.get());
    buffer.clear();
    System.out.println();
  }
} catch (IOException e) {
    System.out.println(e.toString());
}
一个
ByteBuffer
知道它包含多少字节(即通过读取操作已放入其中)。使用
flip
可以准备缓冲区,以便读取它们,例如使用示例中的循环或写入另一个通道。当您知道您已经处理了全部内容时,可以使用
清除
将缓冲区设置为初始状态,从开始到结束都可以填充


否则,如果它可能包含未处理的数据,请改用
compact
,这会将未处理的数据移动到缓冲区的开头,并准备在它们之后接收更多数据,因此,在后续的
read
flip
之后,您就有了上一次迭代的挂起数据,然后是最近的读取操作的数据,可以作为单个序列进行处理。(这就是
阅读器在解码时内部处理不完整字符序列的方式)

text.txt可以更好地用于示例。