2011-05-09 80 views
5

什么是将java.nio.ByteBuffer a转换为(新创建的)CharBuffer bchar[] b的最快方法。Fast ByteBuffer to CharBuffer or char []

通过这样做很重要,即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:-128具有相同的(低级8)位作为char:128。因此,我认为“最好”的解释将如我上面所述,因为这些位是相同的。

之后,我还需要反之亦然翻译:最有效的方式来获得char[]java.nio.CharBuffer回到一个java.nio.ByteBuffer

+3

你想用这个字符缓冲区做什么?如果你输入一个2字节的字符会发生什么?翻译后的字节数组应该如何显示?根据你的需要,最有效的方法可能是不转换。 – Ishtar 2011-05-09 12:06:21

+1

换句话说,您正在寻找将ByteBuffer的内容解释为使用ISO-8859-1编码的字符序列? – Anon 2011-05-09 12:34:54

+0

假设是,'char []'缓冲区中没有大于'0xff'的值来进行反向转换。任何行为/崩溃都可以(“未指定”)。 ISO-8859-1?据我所知,有些字节不能被任何代码页翻译(例如'\ 0')?我认为,如果转储8位数据流,许多代码转换库不会很好地处理它。但我不了解Java,我会查找它。想象一下,我有图片/图像数据。 – towi 2011-05-09 12:49:25

回答

11

所以,你想要的是使用编码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类预实例字符集的情况下,使您可以使用

CharBuffer result = StandardCharsets.ISO_8859_1.decode(byteBuffer); 

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

代替。 (这些行与之前的行相同,只是查找起来更容易,不会出现错误输入名称的风险,也不需要捕捉不可能的异常。)

+1

java.nio.StandardCharsets.ISO_8859_1及其同级提供对字符集的简单引用,无需查找字符串或抛出异常。 – davenpcj 2013-09-21 21:23:10

+0

谢谢你的提示,我更新了答案。 – 2013-09-23 19:34:49

6

我同意@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); 
+0

好的,这是通用的,安全的。谢谢。但我希望可能会有API调用? – towi 2011-05-09 12:55:16

+0

您可以确定编码以您想要的方式工作。您可以尝试使用“US-ASCII”,但我不知道它适用于所有0 - 255. – 2011-05-09 12:59:14

+1

不,US-ASCII仅适用于0-127,其他字节已映射(使用Java时,不使用CharSet API更好的控制)到''?'',其他字符到'(字节)'?''。使用ISO-8859-1完整覆盖8位范围,即做你的循环。 – 2011-05-09 19:28:18

0

除了推迟创建CharBuffer,您可能没有人能够得到。 如果使用数据作为字符的代码并不严格需要CharBuffer或char [],只需执行简单的即时转换;使用ByteBuffer.get()(相对或绝对),转换为char(注意:正如所指出的那样,您不得不明确地屏蔽事物;否则值128-255将被符号扩展为不正确的值0xFF80 - 0xFFFF;不需要7位ASCII码),并使用它。