ByteBuffer.asCharBuffer() 使用什么字符集?它似乎在我的系统上将 3 个字节转换为 1 个字符。
相关说明,CharsetDecoder 与 ByteBuffer.asCharBuffer() 有何关系?
更新:关于我正在使用的 ByteBuffer 的实现,我正在调用
ByteBuffer.allocate(1024).asCharBuffer()
。我无法评论幕后使用的实现。
对于第一个问题 - 我相信它使用 Java 的本机字符编码(UTF-16)。
据我了解,它没有任何用处。它只是假设它已经被正确解码为 Java 字符串,这意味着 UTF-16。这可以通过查看 HeapByteBuffer 的源代码来显示,其中返回的 charbuffer 最终调用(小端版本):
static private char makeChar(byte b1, byte b0) {
return (char)((b1 << 8) | (b0 & 0xff));
}
因此,这里处理的唯一事情是您负责的其余部分的字节序。这也意味着使用可以指定编码的 Decoder 类通常更有用。
看jdk7,
jdk/src/share/classes/java/nio
X-Buffer.java.template
将 ByteBuffer.allocate()
映射到 Heap-X-Buffer.java.template
Heap-X-Buffer.java.template
将 ByteBuffer.asCharBuffer()
映射到 ByteBufferAs-X-Buffer.java.template
ByteBuffer.asCharBuffer().toString()
调用CharBuffer.put(CharBuffer)
但我不知道这会导致什么最终这可能会导致
Bits.makeChar()
,其定义为:
static private char makeChar(byte b1, byte b0) {
return (char)((b1 << 8) | (b0 & 0xff));
}
但我不知道怎么办。
我想扩展 @Petteri H 的答案。 确实,
asCharBuffer()
期望 ByteBuffer
已经是 UTF-16 编码的。不执行进一步的编码转换。您可以使用下面的代码运行实验。
首先,创建一个名为
test.txt
的纯文本文件,其中包含几行。
Hello World
Hi Moon
Howdy Jupiter
该文件默认采用 UTf-8 编码。我们预计这是一个问题,因为
CharBuffer
将读取两个连续的字节来构造一个字符并给你垃圾值。稍后我们会解决这个问题。
以下代码将简单地转储文件中的每个字符。注意:它将把每个双字节序列视为一个字符。
import java.io.RandomAccessFile;
import java.nio.*;
import java.nio.channels.FileChannel;
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
try (var file = new RandomAccessFile("test.txt", "r")) {
var mappedMemory = file.getChannel()
.map(FileChannel.MapMode.READ_ONLY, 0, file.length());
var buff = mappedMemory.asCharBuffer();
for (int i = 0; i < buff.length(); ++i) {
var ch = buff.get(i);
System.out.print(ch);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
当您运行代码时,您将看到意外的字符:
䡥汬漠坯牬搊䡩⁍潯渊䡯睤礠䩵灩瑥爊
现在,让我们使用 UTF-16 对同一文件进行编码。
iconv -f utf-8 -t utf-16 test.txt > test-fixed.txt
将 Java 代码更改为
test-fixed.txt
。然后再次运行。
现在,您将看到正确的输出。
有趣的是,
CharBuffer
会跳过 test-fixed.txt
文件将具有的 BOM 标记。