web-dev-qa-db-ja.com

Java ByteBuffer to String

これは、この方法で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と関連する問題から/への文字列の変換 のような他のアプローチはより複雑に見えるためです。

102
vikky.rk

EDIT(2018):@ xinyongChengが編集した兄弟の答えは、より簡単なアプローチです、受け入れられた答えでなければなりません。

プラットフォームのデフォルトの文字セットにバイトが含まれていることがわかっている場合、アプローチは妥当です。この例では、k.getBytes()はプラットフォームのデフォルトの文字セットのバイトを返すため、これは真です。

より頻繁に、エンコードを指定する必要があります。ただし、リンクする質問よりも簡単な方法があります。 String APIは、特定のエンコーディングでStringとbyte []配列の間で変換するメソッドを提供します。これらの方法は、CharsetEncoder/CharsetDecoder ""デコード[エンコード]プロセスをさらに制御する必要がある場合に使用することをお勧めします。 "

特定のエンコーディングで文字列からバイトを取得するには、兄弟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)を使用して、バッファーからバイトをバイト配列に取得します。

71
Andy Thomas

Andy Thomasが述べたように、ByteBufferを問題なくStringにデコードする簡単な方法があります。

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

これを試して:

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

NB。エンコードを知らずにバイト配列を文字列に正しく変換することはできません。

これが役立つことを願っています

16
Dan Bray

ただ指摘したいのですが、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では機能しない場合があります。

11
Fuwjax

単に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の回答を参照してください。

5
Alex Yarmula

Javaを使用して文字列を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();
}

印刷された裸の文字列を最初に印刷し、次にarray()にキャストされた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として出力します。

こんにちは
ããã«ã¡ã¯
1
Eric Leschinski

エンコードの問題は別として、リンクされているより複雑なコードの一部は、単にすべてのバイトをエンコードするのではなく、問題のByteBufferの「アクティブな」部分を取得する問題になります。バッキング配列全体で(これらの回答の例の多くが行うように)。

1
Jas

この質問の根源はバイトを文字列にデコードする方法ですか?

これは、Java NIO CharSetを使用して実行できます。

public final CharBuffer decode(ByteBuffer bb)

enter image description here

0
宏杰李
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");
};
0
Koenraad Appelo