[java] 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 와 같은 다른 접근 방식 : ByteBuffer와의 문자열 변환 및 관련 문제 가 더 복잡해 보이기 때문입니다.



답변

편집 (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)하여 버퍼에서 바이트 배열로 바이트를 가져옵니다.


답변

Andy Thomas가 언급 한 문제없이 a ByteBuffer를 a 로 디코딩하는 더 간단한 방법이 있습니다 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);

일반적으로 buffer.hasArray ()는 사용 사례에 따라 항상 true 또는 false입니다. 실제로 어떤 상황에서도 실제로 작동하기를 원하지 않는 한 필요하지 않은 브랜치를 최적화하는 것이 안전합니다. 그러나 나머지 답변은 ByteBuffer.allocateDirect ()를 통해 생성 된 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 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());
  • 먼저 채널을 만들고 버퍼에서 읽습니다.
  • 그런 다음 디코딩 메서드는 Latin1 버퍼를 char 버퍼로 디코딩합니다.
  • 그런 다음 결과를 예를 들어 String에 넣을 수 있습니다.

답변

인코딩 문제를 제외하고 링크 된 더 복잡한 코드 중 일부는 단순히 모든 바이트를 인코딩하는 것이 아니라 해당 ByteBuffer의 “활성”부분 (예 : 위치 및 제한 사용)을 가져 오는 문제로 이어진다는 점에 유의하십시오. 전체 백업 배열에서 (이 답변의 많은 예가 그렇듯이).