Java ByteBuffer для строки

это правильный подход для преобразования 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 ответов


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

более часто вы захотите указать кодировку. Однако, есть более простой способ сделать это, чем вопрос, который вы связаны. API String предоставляет методы, которые преобразуют между строкой и массивом 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) чтобы получить байты из буфера в массив байтов.

редактировать

в качестве побочной проблемы в примере кода выше вызова 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 в вопросе (например, с помощью позиции и предела), а не просто кодирования всех байтов во всем массиве поддержки (как многие из примеров в этих ответах).


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

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

public final CharBuffer decode(ByteBuffer bb)

enter image description here