快速将ByteBuffer转换为CharBuffer或char[]

5
什么是将java.nio.ByteBuffer a转换为(新创建的)CharBuffer bchar[] b的最快方法?
在执行此操作时,重要的是要确保a[i] == b[i]。这意味着不是a[i]a[i+1]一起组成值b[j](就像getChar(i)所做的那样),而应该将值“分散”。
byte a[] = { 1,2,3, 125,126,127, -128,-127,-126 } // each a byte (which are signed)
char b[] = { 1,2,3, 125,126,127,  128, 129, 130 } // each a char (which are unsigned)

请注意,byte:-128char:128具有相同的(低8)位。因此,我认为“最佳”解释应该是如上所述,因为这些位是相同的。
此外,我还需要“反之亦然”的翻译:将char[]java.nio.CharBuffer有效地转换回java.nio.ByteBuffer的最有效方法。

3
你想对这个字符缓冲区做什么?如果你输入一个2字节的字符,会发生什么?那么翻译后的字节数组应该是什么样子的?根据你的需求,最有效的方式可能是根本不进行转换。 - Ishtar
1
жҚұеЏӨиҮқиҮөпәЊж‚ЁеёЊжњ›е°†ByteBufferзљ„е†…е®№и§Әй‡ЉдёғдҢүз”ЁISO-8859-1зә–码的字符еғЏе€—пәџ - Anon
假设在反向转换的char[]缓冲区中没有大于0xff的值。任何行为/崩溃都可以(“未指定”)。ISO-8859-1?据我所知,有些字节无法通过任何代码页进行转换(例如\0)?我认为许多代码页转换库不会很好地处理8位数据流。但是我不知道Java,我会查一下。想象一下我有图片/图像数据。 - towi
1
什么?如果你有图片/图像数据,那你为什么还关心字符呢?也许如果你描述一下你想要实现的目标,而不是你想要采取的方法,你会得到更相关的答案。 - Anon
2
@towi - 那么你想要的数据类型就叫做“short”。 - Anon
显示剩余2条评论
3个回答

13

所以,你想要使用编码ISO-8859-1进行转换。

我不保证效率,但至少写起来相当简短:

CharBuffer result = Charset.forName("ISO-8859-1").decode(byteBuffer);

另一种方式是:

ByteBuffer result = Charset.forName("ISO-8859-1").encode(charBuffer);
请与其他解决方案进行比较。 (公平起见,Charset.forName 部分不应包括在内,并且只应执行一次,而不是针对每个缓冲区再次执行。)
从Java 7开始,还有一个StandardCharsets类,其中预先实例化了Charset实例,因此您可以使用
CharBuffer result = StandardCharsets.ISO_8859_1.decode(byteBuffer);

ByteBuffer result = StandardCharsets.ISO_8859_1.encode(charBuffer);

相反,使用这些代码行可以实现相同的效果,只不过查找更加容易,不会出现拼写错误的风险,并且不需要捕获无法处理的异常。


1
java.nio.StandardCharsets.ISO_8859_1及其同类提供了一个简单的字符集参考,无需字符串查找或抛出异常。 - davenpcj

5

我同意@Ishtar的观点,建议尽量避免完全转换为新结构,只在需要时进行转换。

但是,如果你有一个堆 ByteBuffer,你可以这样做。

ByteBuffer bb = ...
byte[] array = bb.array();
char[] chars = new char[bb.remaining()];
for (int i = 0; i < chars.length; i++)
    chars[i] = (char) (array[i + bb.position()] & 0xFF);

好的,那很通用和安全。谢谢。但我希望可能有一个API调用来实现这个? - towi
你可以确信编码按照你的意愿工作。你可以尝试使用“US-ASCII”,但我不确定它是否适用于所有0-255。 - Peter Lawrey
1
不,US-ASCII仅适用于0-127,其他字节被映射为“?”(在Java中,如果不使用CharSet API进行更精细的控制),其他字符则被映射为(byte)'?'。使用ISO-8859-1以完全覆盖8位范围,即执行您的循环所做的操作。 - Paŭlo Ebermann

0

除了推迟CharBuffer的创建,您可能可以在没有它的情况下解决问题。 如果正在使用数据作为字符的代码不严格需要CharBuffer或char[],只需进行简单的即时转换;使用ByteBuffer.get()(相对或绝对),转换为char(请注意:如指出,不幸的是,您必须显式掩盖一些内容;否则值128-255将被扩展为不正确的值0xFF80-0xFFFF;7位ASCII不需要),然后使用它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接