我知道这是一个非常笼统的问题,但我快要生气了。
我使用了这段代码:
String ucs2Content = new String(bufferToConvert, inputEncoding);
byte[] outputBuf = ucs2Content.getBytes(outputEncoding);
return outputBuf;
但我读到最好使用 CharsetDecoder 和 CharsetEncoder(我的内容可能包含目标编码之外的某些字符)。我刚刚编写了这段代码,但存在一些问题:
// Create the encoder and decoder for Win1252
Charset charsetInput = Charset.forName(inputEncoding);
CharsetDecoder decoder = charsetInput.newDecoder();
Charset charsetOutput = Charset.forName(outputEncoding);
CharsetEncoder encoder = charsetOutput.newEncoder();
// Convert the byte array from starting inputEncoding into UCS2
CharBuffer cbuf = decoder.decode(ByteBuffer.wrap(bufferToConvert));
// Convert the internal UCS2 representation into outputEncoding
ByteBuffer bbuf = encoder.encode(CharBuffer.wrap(cbuf));
return bbuf.array();
实际上这段代码向缓冲区附加了一个空字符序列!!!!!
有人能告诉我问题出在哪里吗?我对 Java 中的编码转换不是很熟练。
在Java中有没有更好的编码转换方式?
最佳答案
您的问题是 ByteBuffer.array()
返回对用作 ByteBuffer 后备存储的数组的直接引用,而不是后备数组有效范围的副本。你必须遵守 bbuf.limit()
(正如 Peter 在他的回应中所做的那样)并且只使用从索引 0
到 bbuf.limit() 的数组内容- 1
。
支持数组中额外的 0 值的原因是 CharsetEncoder 如何创建生成的 ByteBuffer 的方式存在轻微缺陷。每个 CharsetEncoder 都有一个“每个字符的平均字节数”,这对于 UCS2 编码器来说似乎简单而正确(2 个字节/字符)。根据这个固定值,CharsetEncoder 最初分配一个 ByteBuffer,其中包含“字符串长度 * 每个字符的平均字节数”字节,在这种情况下,例如10 个字符长的字符串需要 20 个字节。然而,UCS2 CharsetEncoder 以 BOM(字节顺序标记)开始,它也占用 2 个字节,因此 10 个字符中只有 9 个适合分配的 ByteBuffer。 CharsetEncoder 检测到溢出并分配一个长度为 2*n+1(n 是 ByteBuffer 的原始长度)的新 ByteBuffer,在本例中为 2*20+1 = 41 字节。由于只需要 21 个新字节中的 2 个来编码剩余的字符,您从 bbuf.array()
获得的数组长度为 41 个字节,但是 bbuf.limit()
将指示实际仅使用前 22 个条目。
关于java - 在 Java : null characters with CharsetDecoder/Encoder 中从 Windows 1252 转换为 UTF8,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6127528/