我知道这是一个非常普遍的问题,但我变得疯了。
我用过这段代码:
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的新ByteBuffer(n是ByteBuffer的原始长度),在这种情况下为2 * 20 + 1 = 41字节。由于21个新字节中只有2个需要对剩余字符进行编码,因此您可以使用该数组 bbuf.array()
将具有41个字节的长度,但是 bbuf.limit()
将指示实际仅使用前22个条目。
你的问题是 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的新ByteBuffer(n是ByteBuffer的原始长度),在这种情况下为2 * 20 + 1 = 41字节。由于21个新字节中只有2个需要对剩余字符进行编码,因此您可以使用该数组 bbuf.array()
将具有41个字节的长度,但是 bbuf.limit()
将指示实际仅使用前22个条目。
我不确定你是如何获得一系列的 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! £€