Java ByteBuffer到String

vik*_*.rk 111 java string serialization bytearray

这是以这种方式将ByteBuffer转换为String的正确方法,

String k = "abcd";
ByteBuffer b = ByteBuffer.wrap(k.getBytes());
String v = new String(b.array());

if(k.equals(v))
    System.out.println("it worked");
else
    System.out.println("did not work");
Run Code Online (Sandbox Code Playgroud)

我问的原因是这看起来太简单了,而其他方法如Java:将字符串转换为ByteBuffer以及相关问题看起来更复杂.

小智 80

Andy Thomas提到了ByteBuffer一种更简单的解码方法,String没有任何问题.

String s = StandardCharsets.UTF_8.decode(byteBuffer).toString();
Run Code Online (Sandbox Code Playgroud)

  • 请注意,UTF-8可能不是将字节转换为字符串(反之亦然)的最佳字符集。有关字节到字符的一对一映射,最好使用ISO-8859-1,请参阅/sf/ask/636861571/ -byte-array。 (2认同)
  • 另外,如果您“真的”不需要字符串,“CharBuffer”“decode()”返回的是“CharSequence”(如“String”),因此您可以避免额外的副本并直接使用它。 (2认同)

And*_*mas 73

EDIT(2018): @xinyongCheng编辑的兄弟答案是一种更简单的方法,应该是公认的答案.

如果您知道字节在平台的默认字符集中,那么您的方法将是合理的.在您的示例中,这是真的,因为k.getBytes()返回平台的默认字符集中的字节.

更常见的是,您需要指定编码.但是,与您链接的问题相比,有一种更简单的方法.String API提供了在特定编码中在String和byte []数组之间进行转换的方法.当需要对解码[编码]过程进行更多控制时,这些方法建议使用CharsetEncoder/CharsetDecoder ."

要从特定编码中的String获取字节,可以使用兄弟getBytes()方法:

byte[] bytes = k.getBytes( StandardCharsets.UTF_8 );
Run Code Online (Sandbox Code Playgroud)

要将具有特定编码的字节放入String,可以使用不同的String构造函数:

String v = new String( bytes, StandardCharsets.UTF_8 );
Run Code Online (Sandbox Code Playgroud)

请注意,这ByteBuffer.array()是一个可选操作.如果您使用数组构造了ByteBuffer,则可以直接使用该数组.否则,如果您想要安全,请使用ByteBuffer.get(byte[] dst, int offset, int length)从缓冲区获取字节到字节数组.


Dan*_*ray 16

试试这个:

new String(bytebuffer.array(), "ASCII");
Run Code Online (Sandbox Code Playgroud)

NB.您无法在不知道其编码的情况下将字节数组正确转换为字符串.

我希望这有帮助

  • UTF-8可能是比ASCII更好的默认猜测? (10认同)
  • 并非所有缓冲区都由数组支持,因此`.array()`可能会抛出异常. (6认同)
  • 考虑到OP使用k.getBytes(),它使用平台的默认字符集,也不应该指定. (3认同)
  • 小心!如果你使用`array()`,你_必须_也使用`arrayOffset()`从数组中的正确位置开始!这是一个微妙的陷阱,因为通常 arrayOffset() 是 0;但是在那些罕见的情况下,如果您不考虑它,您将很难发现错误。 (3认同)

Fuw*_*jax 12

只是想指出,假设ByteBuffer.array()始终有效是不安全的.

byte[] bytes;
if(buffer.hasArray()) {
    bytes = buffer.array();
} else {
    bytes = new byte[buffer.remaining()];
    buffer.get(bytes);
}
String v = new String(bytes, charset);
Run Code Online (Sandbox Code Playgroud)

通常,buffer.hasArray()将始终为true或false,具体取决于您的用例.在实践中,除非您真的希望它在任何情况下都能工作,否则可以安全地优化您不需要的分支.但其余的答案可能不适用于通过ByteBuffer.allocateDirect()创建的ByteBuffer.

  • 小心!如果你使用`array()`,你_必须_也使用`arrayOffset()`从数组中的正确位置开始!这是一个微妙的陷阱,因为通常 arrayOffset() 是 0;但是在那些罕见的情况下,如果您不考虑它,您将很难发现错误。 (2认同)

Ale*_*ula 5

关于简单调用的答案array()不是很正确:当缓冲区已被部分消耗,或者是在引用数组的一部分时(您可以ByteBuffer.wrap在给定偏移量的数组上,不必从头开始),我们必须考虑在我们的计算中。这是在所有情况下都适用于缓冲区的通用解决方案(不涵盖编码):

if (myByteBuffer.hasArray()) {
    return new String(myByteBuffer.array(),
        myByteBuffer.arrayOffset() + myByteBuffer.position(),
        myByteBuffer.remaining());
} else {
    final byte[] b = new byte[myByteBuffer.remaining()];
    myByteBuffer.duplicate().get(b);
    return new String(b);
}
Run Code Online (Sandbox Code Playgroud)

有关编码的问题,请参阅Andy Thomas的答案。