私はソケット接続にJava NIOを使用しており、プロトコルはテキストベースであるため、文字列をByteBufferに変換してからSocketChannelに書き込み、着信ByteBufferを元に戻す必要があります。現在、私はこのコードを使用しています:
_public static Charset charset = Charset.forName("UTF-8");
public static CharsetEncoder encoder = charset.newEncoder();
public static CharsetDecoder decoder = charset.newDecoder();
public static ByteBuffer str_to_bb(String msg){
try{
return encoder.encode(CharBuffer.wrap(msg));
}catch(Exception e){e.printStackTrace();}
return null;
}
public static String bb_to_str(ByteBuffer buffer){
String data = "";
try{
int old_position = buffer.position();
data = decoder.decode(buffer).toString();
// reset buffer's position to its original so it is not altered:
buffer.position(old_position);
}catch (Exception e){
e.printStackTrace();
return "";
}
return data;
}
_
これはほとんどの場合に機能しますが、これがこの変換の各方向を実行するのに好ましい(または最も簡単な)方法であるかどうか、または他に試す方法があるかどうかは疑問です。時々、そして一見ランダムに、encode()
とdecode()
の呼び出しは、変換のたびに新しいByteBufferオブジェクトを使用していても、_Java.lang.IllegalStateException: Current state = FLUSHED, new state = CODING_END
_例外、または同様の例外をスローします終わらせる。これらのメソッドを同期する必要がありますか? StringsとByteBuffersの間で変換するより良い方法はありますか?ありがとう!
CharsetEncoder
および CharsetDecoder
APIの説明を確認してください-メソッドの特定のシーケンスに従う必要がありますこの問題を回避するには、calls。たとえば、CharsetEncoder
の場合:
reset
メソッドを使用してエンコーダーをリセットします。encode
メソッドを0回以上呼び出し、endOfInput引数にfalse
を渡し、呼び出し間で入力バッファーを埋め、出力バッファーをフラッシュします。encode
メソッドを呼び出し、endOfInput引数にtrue
を渡します。その後flush
メソッドを呼び出して、エンコーダーが内部状態を出力バッファーにフラッシュできるようにします。ちなみに、これは私がNIOで使用しているアプローチと同じですが、同僚の一部はASCIIのみを使用しているという知識で各文字を直接バイトに変換していますが、おそらくより高速だと思います。
状況が変わっていない限り、あなたは
public static ByteBuffer str_to_bb(String msg, Charset charset){
return ByteBuffer.wrap(msg.getBytes(charset));
}
public static String bb_to_str(ByteBuffer buffer, Charset charset){
byte[] bytes;
if(buffer.hasArray()) {
bytes = buffer.array();
} else {
bytes = new byte[buffer.remaining()];
buffer.get(bytes);
}
return new String(bytes, charset);
}
通常、buffer.hasArray()は、ユースケースに応じて常にtrueまたは常にfalseになります。実際には、どのような状況でも本当に動作させたい場合を除き、不要なブランチを最適化して削除しても安全です。
Adamskiによる回答は良いものであり、一般的なエンコード方法を使用する場合のエンコード操作の手順を説明しています(入力の1つとしてバイトバッファを使用します)
ただし、(この説明で)問題のメソッドは、encode-encode(CharBuffer in)のバリアントです。これは、エンコード操作全体を実装する便利なメソッドです。 (Java P.S.のドキュメントリファレンスを参照してください。)
ドキュメントに従って、したがって、エンコード操作がすでに進行中の場合、このメソッドを呼び出すべきではありませんマルチスレッド環境での静的エンコーダー/デコーダー)。
個人的には、convenienceメソッド(より一般的なエンコード/デコードメソッド)を使用するのが好きです。
ZenBlenderとAdamskiは、コメントでこれを安全に行うための複数の方法オプションをすでに提案しています。ここにすべてをリストします。
追伸.
Javaドキュメントリファレンス: