Java ByteBuffer для строки

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

Ответ 1

РЕДАКТИРОВАТЬ (2018): отредактированный ответ родного брата @xinyongCheng - более простой подход, и он должен быть принятым ответом.

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

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

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

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

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

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

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

Ответ 2

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

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

Ответ 3

Попробуйте следующее:

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

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

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

Ответ 4

Просто хотел указать, небезопасно предположить, что 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() всегда будет true или false в зависимости от вашего варианта использования. На практике, если вы действительно не хотите, чтобы он работал ни при каких обстоятельствах, безопасно оптимизировать отрасль, в которой вы не нуждаетесь. Но остальные ответы могут не работать с ByteBuffer, созданным через ByteBuffer.allocateDirect().

Ответ 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);
}

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

Ответ 6

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

Ответ 7

Преобразовать строку в ByteBuffer, затем из ByteBuffer обратно в String с помощью 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, наложенную на массив():

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:

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

Ответ 8

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

это можно сделать с помощью JAVA NIO CharSet:

public final CharBuffer decode(ByteBuffer bb)

enter image description here

Ответ 9

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