在Java中从Windows 1252转换为UTF8:使用CharsetDecoder/Encoder的空字符

rob*_*bob 11 java encoding

我知道这是一个非常普遍的问题,但我变得疯了.

我用过这段代码:

String ucs2Content = new String(bufferToConvert, inputEncoding);        
        byte[] outputBuf = ucs2Content.getBytes(outputEncoding);        
        return outputBuf;
Run Code Online (Sandbox Code Playgroud)

但我读到最好使用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();
Run Code Online (Sandbox Code Playgroud)

实际上,这段代码在缓冲区附加了一个空字符序列 !!!!!

有人能告诉我问题出在哪里?我不熟悉Java中的编码转换.

有没有更好的方法来转换Java中的编码?

jar*_*bjo 7

您的问题是ByteBuffer.array()返回对用作ByteBuffer的后备存储的数组的直接引用,而不是后备数组的有效范围的副本.你必须服从bbuf.limit()(如彼得在他的反应做了),只是使用数组内容从索引0bbuf.limit()-1.

后备数组中额外0值的原因是CharsetEncoder创建生成的ByteBuffer的方式存在轻微缺陷.每个CharsetEncoder都有一个"每个字符的平均字节数",对于UCS2编码器来说,它看起来简单而正确(2个字节/字符).遵守此固定值,CharsetEncoder最初为字节长度为每个字符的"字符串长度*平均字节数"字节分配ByteBuffer,在这种情况下,对于10个字符长的字符串,例如20个字节.然而,UCS2 CharsetEncoder以BOM(字节顺序标记)开始,它也占用2个字节,因此10个字符中只有9个符合分配的ByteBuffer.CharsetEncoder检测溢出并分配一个长度为2*n + 1的新ByteBuffer(n是ByteBuffer的原始长度),在这种情况下为2*20 + 1 = 41字节.由于21个新字节中只有2个需要对剩余字符进行编码,因此您获得的数组bbuf.array()将具有41个字节的长度,但bbuf.limit()将指示实际仅使用前22个条目.


归档时间:

查看次数:

10967 次

最近记录:

12 年,10 月 前