147

这是以这种方式将 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");

我问的原因是这看起来太简单了,而其他方法,如Java:Converting String to and from ByteBuffer 和相关问题看起来更复杂。

4

11 回答 11

148

安迪·托马斯(Andy Thomas)提到,有一种更简单的方法可以毫无问题地将 a 解码ByteBuffer为 a 。String

String s = StandardCharsets.UTF_8.decode(byteBuffer).toString();
于 2016-10-04T06:01:33.003 回答
88

编辑(2018 年): @xinyongCheng编辑的同级答案是一种更简单的方法,应该是公认的答案

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

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

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

byte[] bytes = k.getBytes( StandardCharsets.UTF_8 );

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

String v = new String( bytes, StandardCharsets.UTF_8 );

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

于 2013-06-28T00:06:21.673 回答
17

试试这个:

new String(bytebuffer.array(), "ASCII");

注意。在不知道其编码的情况下,您无法正确地将字节数组转换为字符串。

我希望这有帮助

于 2013-06-27T23:34:13.727 回答
15

只是想指出,假设 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);

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

于 2015-06-15T22:52:05.743 回答
8

仅指调用的答案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);
}

有关与编码相关的问题,请参阅 Andy Thomas 的回答。

于 2015-11-24T16:55:30.363 回答
2

这个问题的根源是如何将字节解码为字符串?

这可以通过 JAVA NIO CharSet 来完成:

public final CharBuffer decode(ByteBuffer bb)

FileChannel channel = FileChannel.open(
  Paths.get("files/text-latin1.txt", StandardOpenOption.READ);
ByteBuffer buffer = ByteBuffer.allocate(1024);
channel.read(buffer);

CharSet latin1 = StandardCharsets.ISO_8859_1;
CharBuffer latin1Buffer = latin1.decode(buffer);

String result = new String(latin1Buffer.array());
  • 首先我们创建一个通道并在缓冲区中读取它
  • 然后 decode 方法将 Latin1 缓冲区解码为 char 缓冲区
  • 然后我们可以将结果,例如,放在一个字符串中
于 2018-04-07T14:59:01.073 回答
1

将 String 转换为 ByteBuffer,然后使用 Java 从 ByteBuffer 转换回 String:

import java.nio.charset.Charset;
import java.nio.*;

String babel = "obufscate thdé alphebat and yolo!!";
System.out.println(babel);
//Convert string to ByteBuffer:
ByteBuffer babb = Charset.forName("UTF-8").encode(babel);
try{
    //Convert ByteBuffer to String
    System.out.println(new String(babb.array(), "UTF-8"));
}
catch(Exception e){
    e.printStackTrace();
}

首先打印打印的裸字符串,然后将 ByteBuffer 转换为 array():

obufscate thdé alphebat and yolo!!
obufscate thdé alphebat and yolo!!

这对我也很有帮助,将字符串减少为原始字节可以帮助检查发生了什么:

String text = "こんにちは";
//convert utf8 text to a byte array
byte[] array = text.getBytes("UTF-8");
//convert the byte array back to a string as UTF-8
String s = new String(array, Charset.forName("UTF-8"));
System.out.println(s);
//forcing strings encoded as UTF-8 as an incorrect encoding like
//say ISO-8859-1 causes strange and undefined behavior
String sISO = new String(array, Charset.forName("ISO-8859-1"));
System.out.println(sISO);

打印解释为 UTF-8 的字符串,然后再打印为 ISO-8859-1:

こんにちは
ããã«ã¡ã¯
于 2016-08-08T18:35:45.373 回答
0

请注意(除了编码问题),一些更复杂的链接代码会遇到问题 ByteBuffer 的“活动”部分(例如通过使用位置和限制),而不是简单地编码所有字节在整个支持数组中(正如这些答案中的许多示例所做的那样)。

于 2015-07-15T19:30:10.070 回答
0
private String convertFrom(String lines, String from, String to) {
    ByteBuffer bb = ByteBuffer.wrap(lines.getBytes());
    CharBuffer cb = Charset.forName(to).decode(bb);
    return new String(Charset.forName(from).encode(cb).array());
};
public Doit(){
    String concatenatedLines = convertFrom(concatenatedLines, "CP1252", "UTF-8");
};
于 2019-07-11T09:08:42.523 回答
0

这是一个将字节缓冲区转换为字符串的简单函数:

public String byteBufferToString(ByteBuffer bufferData) {
    byte[] buffer = new byte[bufferData.readableByteCount()];
    // read bufferData and insert into buffer 
    data.read(buffer);
    // CharsetUtil supports UTF_16, ASCII, and many more
    String text = new String(buffer, CharsetUtil.UTF_8);
    System.out.println("Text: "+text);
    return text;
}
于 2020-08-13T13:45:12.847 回答
0

这是在java.nio.ByteBuffer实例上对我有用的唯一方法:

String fileContent = new String(bb.array(), StandardCharsets.UTF_8);

相关代码片段如下:

import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;


Path path = Paths.get("/home/binita/testbb");
FileChannel fileChannel = FileChannel.open(path, 
                 EnumSet.of(StandardOpenOption.READ
                    )
                 );  
            
ByteBuffer bb = ByteBuffer.allocate(1024);
int bytesRead = fileChannel.read(bb);
if(bytesRead > 0) {
 String fileContent = new String(bb.array(), StandardCharsets.UTF_8);
}
于 2021-07-29T11:10:44.163 回答