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

时间:2011-05-25 16:11:50

标签: java encoding

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

我使用了这段代码:

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中转换编码?

2 个答案:

答案 0 :(得分:7)

您的问题是ByteBuffer.array()返回对用作ByteBuffer的后备存储的数组的直接引用,而不是后备数组的有效范围的副本。您必须服从bbuf.limit()(正如Peter在回复中所做的那样),并且只使用索引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个条目使用

答案 1 :(得分:4)

我不确定你是如何获得一系列null字符的。试试这个

String outputEncoding = "UTF-8";
Charset charsetOutput = Charset.forName(outputEncoding);
CharsetEncoder encoder = charsetOutput.newEncoder();

// Convert the byte array from starting inputEncoding into UCS2
byte[] bufferToConvert = "Hello World! £€".getBytes();
CharBuffer cbuf = decoder.decode(ByteBuffer.wrap(bufferToConvert));

// Convert the internal UCS2 representation into outputEncoding
ByteBuffer bbuf = encoder.encode(CharBuffer.wrap(cbuf));
System.out.println(new String(bbuf.array(), 0, bbuf.limit(), charsetOutput));

打印

Hello World! £€