Java ByteBuffer to String


это правильный подход для преобразования ByteBuffer в строку таким образом,

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 и связанные с ним проблемы, выглядят более сложными.

8 87

8 ответов:

ваш подход был бы разумным, если бы вы знали, что байты находятся в кодировке по умолчанию платформы. В вашем примере это верно, потому что k.getBytes() возвращает байты в кодировке платформы по умолчанию.

чаще, вы хотите, чтобы указать кодировку. Однако, есть более простой способ сделать это, чем вопрос, который вы связаны. String API предоставляет методы, которые преобразуются между строкой и массивом byte[] в определенной кодировке. Эти методы предлагают использовать CharsetEncoder/CharsetDecoder " когда требуется больше контроля над процессом декодирования [кодирования]."

import java.nio.charset.Charset;

чтобы получить байты из строки в определенной кодировке, вы можете использовать метод sibling getBytes ():

byte[] bytes = k.getBytes( Charset.forName("UTF-8" ));

чтобы поместить байты с определенной кодировкой в строку, вы можете использовать другой строковый конструктор:

String v = new String( bytes, Charset.forName("UTF-8") );

отметим, что ByteBuffer.array() является необязательной операцией. Если вы построили свой ByteBuffer с массивом, вы можете использовать этот массив напрямую. В противном случае, если вы хотите быть в безопасности, используйте ByteBuffer.get(byte[] dst, int offset, int length) чтобы получить байты из буфера в массив байтов.

EDIT

как побочный вопрос, в примере кода выше вызов Charset.forName("UTF-8") должны работать для всех версий Java, начиная с 1.4.

если вы используете Java 7 или более поздней версии, вы можете использовать java.nio.charset.StandardCharsets.UTF_8. (отметил Бенкирби в своем комментарии ниже.)

если вы используете гуавы, вы можете использовать com.google.common.base.Charsets.UTF_8. (отмечено spacecamel в своем комментарии ниже.)

существует более простой подход к декодированию a ByteBuffer на String без каких-либо проблем, упомянутых Энди Томасом.

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

попробуйте это:

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

NB. вы не можете правильно преобразовать массив байтов в строку, не зная его кодировку.

надеюсь, это поможет

просто хотел отметить, что это не безопасно предполагать 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, который был создан через ByteBuffer.allocateDirect().

ответы, относящиеся к простому вызову 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);
}

для проблем, связанных с кодированием, см. ответ Энди Томаса.

преобразовать строку в ByteBuffer, а затем из ByteBuffer обратно в строку с помощью Java:

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:

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

обратите внимание (помимо проблемы кодирования), что некоторые из более сложных связанных кодов связаны с проблемой получения "активной" части рассматриваемого ByteBuffer (например, с помощью position и limit), а не просто кодирования всех байтов во всем резервном массиве (как это делают многие примеры в этих ответах).

корень этого вопроса как декодировать байты в строку?

Это можно сделать с помощью кодировки JAVA NIO:

public final CharBuffer decode(ByteBuffer bb)

enter image description here