字节缓冲到字符串

以这种方式将 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: 字符串与 ByteBuffer 之间的转换及相关问题)看起来更复杂。

251724 次浏览

试试这个:

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

注意,如果不知道字节数组的编码,就无法正确地将其转换为字符串。

希望这个能帮上忙

编辑(2018) : 编辑的兄弟姐妹 @ xinyongCheng 是一个更简单的方法,应该是可以接受的答案

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

更常见的情况是,您需要指定编码。然而,有一个比你链接的问题更简单的方法来做到这一点。StringAPI 提供了在 String 和 byte []数组之间以特定编码进行转换的方法。这些方法建议使用 CharsetEncoder/CharsetDecder “当需要对解码[编码]过程进行更多控制时。”

要以特定的编码方式从 String 获取字节,可以使用兄弟 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)将字节从缓冲区获取到字节数组中。

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

HasArray ()通常是 true 还是 false 取决于您的用例。实际上,除非您真的希望它在任何情况下都能工作,否则优化掉不需要的分支是安全的。但是其余的答案可能不适用于通过 ByteBuffer.allocateDirect ()创建的 ByteBuffer。

注意(除了编码问题) ,一些更复杂的代码链接会遇到问题,比如使用位置和限制来获取 ByteBuffer 的“活动”部分,而不是简单地编码整个备份数组中的所有字节(这些答案中的许多例子都是这样做的)。

简单地调用 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 的答案。

使用 Java: 将 String 转换为 ByteBuffer,然后从 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:

こんにちは
ããã«ã¡ã¯

Andy Thomas 提到,有一种更简单的方法可以将 ByteBuffer解码成 String而不会出现任何问题。

String s = StandardCharsets.UTF_8.decode(byteBuffer).toString();

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

这可以通过 JAVA NIO CharSet 实现:

Public final CharBuffer 解码器(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());
  • 首先,我们创建一个通道并在缓冲区中读取它
  • 然后解码方法将 Latin1缓冲区解码为字符缓冲区
  • 然后我们可以将结果放在一个 String 中
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");
};

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

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;
}

这是我在 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);
}