【问题标题】:Fast ByteBuffer to CharBuffer or char[]快速 ByteBuffer 到 CharBuffer 或 char[]
【发布时间】:2011-05-09 11:32:28
【问题描述】:

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 的最有效方法。

【问题讨论】:

  • 你想用这个字符缓冲区做什么?如果你输入一个 2 字节的字符会发生什么?翻译后的字节数组应该是什么样子?根据您的需要,最有效的方法可能是根本不转换。
  • 换句话说,您希望将ByteBuffer 的内容解释为使用 ISO-8859-1 编码的字符序列?
  • 假设在char[] 缓冲区中没有大于0xff 的值用于反向翻译。任何行为/崩溃都可以(“未指定”)。 ISO-8859-1?据我所知,有些字节不能被任何代码页翻译(例如\0)?我认为如果你转储一个 8 位数据流,许多代码页转换库都不能很好地接受它。但我不了解 Java,我会查一下。想象一下我有图片/图像数据。
  • 嗯?如果你有图片/图像数据,那你为什么要关心字符呢?也许如果您描述了您想要完成的工作,而不是您想要完成的方法,您会得到更相关的答案。
  • @towi - 那么你想要的数据类型就叫做short

标签: java bytearray nio bytebuffer arrays


【解决方案1】:

所以,你想要的是使用编码 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 开始,还有带有预实例化 Charset 实例的 StandardCharsets 类,因此您可以使用

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

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

相反。 (这几行和前面几行一样,只是查找更容易,没有错误输入名称的风险,也不需要捕获不可能的异常。)

【讨论】:

  • java.nio.StandardCharsets.ISO_8859_1 及其对等体提供对字符集的简单引用,无需字符串查找或抛出异常。
【解决方案2】:

我同意@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 调用?
  • 您可以确保编码以您想要的方式工作。您可以尝试“US-ASCII”,但我不知道它适用于所有 0 - 255。
  • 不,US-ASCII 仅用于 0-127,其他字节映射(在 Java 中,当不使用 CharSet API 进行更精细控制时)映射到 '?',其他字符映射到 (byte)'?'。使用 ISO-8859-1 来完全覆盖 8 位范围,即执行循环所做的工作。
【解决方案3】:

除了推迟创建 CharBuffer 之外,您也许可以在没有 CharBuffer 的情况下度过难关。 如果将数据用作字符的代码并不严格需要 CharBuffer 或 char[],只需进行简单的即时转换即可;使用 ByteBuffer.get() (相对或绝对),转换为 char (注意:正如所指出的,不幸的是,您必须明确地屏蔽事物;否则值 128-255 将被符号扩展为不正确的值,0xFF80 - 0xFFFF;不需要7 位 ASCII),并使用它。

【讨论】:

    猜你喜欢
    • 2010-09-22
    • 2020-03-28
    • 1970-01-01
    • 1970-01-01
    • 2012-06-27
    • 1970-01-01
    • 1970-01-01
    • 2019-08-16
    • 1970-01-01
    相关资源
    最近更新 更多