Ich verwende Java NIO für meine Socket-Verbindungen und mein Protokoll basiert auf Text. Daher muss ich in der Lage sein, Strings in ByteBuffers zu konvertieren, bevor ich sie in den SocketChannel schreibe, und die eingehenden ByteBuffers wieder in Strings konvertieren. Derzeit verwende ich diesen Code:
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;
}
Dies funktioniert die meiste Zeit, aber ich frage mich, ob dies der bevorzugte (oder einfachste) Weg ist, um jede Richtung dieser Konvertierung durchzuführen, oder ob es einen anderen Weg gibt, es zu versuchen. Gelegentlich und scheinbar zufällig, um Anrufe encode()
und decode()
eine werfen
java.lang.IllegalStateException: Current state = FLUSHED, new state = CODING_END
Ausnahme oder ähnliche, auch wenn ich eine Umwandlung eines neues ByteBuffer Objekt jedes Mal bin mit gemacht wird . Muss ich diese Methoden synchronisieren? Gibt es eine bessere Möglichkeit, zwischen Strings und ByteBuffers zu konvertieren? Vielen Dank!
quelle
Antworten:
Überprüfen Sie die
CharsetEncoder
undCharsetDecoder
API-Beschreibungen - Sie sollten eine bestimmte Folge von Methodenaufrufen befolgen , um dieses Problem zu vermeiden. Zum Beispiel fürCharsetEncoder
:reset
Methode zurück, es sei denn, er wurde zuvor noch nicht verwendet.encode
Methode null oder mehrmals auf, solange zusätzliche Eingaben verfügbar sind, übergeben Siefalse
das Argument endOfInput, füllen Sie den Eingabepuffer und leeren Sie den Ausgabepuffer zwischen den Aufrufen.encode
Methode ein letztes Mal auf und übergeben Sietrue
das Argument endOfInput. und dannflush
Methode auf, damit der Encoder jeden internen Status in den Ausgabepuffer leeren kann.Übrigens ist dies der gleiche Ansatz, den ich für NIO verwende, obwohl einige meiner Kollegen jedes Zeichen direkt in ein Byte konvertieren, da sie nur ASCII verwenden, was ich mir wahrscheinlich schneller vorstellen kann.
quelle
Wenn sich nichts geändert hat, sind Sie besser dran
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); }
Normalerweise ist buffer.hasArray () je nach Anwendungsfall entweder immer wahr oder immer falsch. In der Praxis ist es sicher, den nicht benötigten Zweig zu optimieren, es sei denn, Sie möchten wirklich, dass er unter keinen Umständen funktioniert.
quelle
Die Antwort von Adamski ist gut und beschreibt die Schritte in einer Codierungsoperation, wenn die allgemeine Codierungsmethode verwendet wird (die einen Bytepuffer als eine der Eingaben verwendet).
Die fragliche Methode (in dieser Diskussion) ist jedoch eine Variante von encode - encode (CharBuffer in) . Dies ist eine bequeme Methode, die den gesamten Codierungsvorgang implementiert . (Siehe Java-Dokumentreferenz in PS)
Gemäß den Dokumenten sollte diese Methode daher nicht aufgerufen werden, wenn bereits eine Codierungsoperation ausgeführt wird (was im ZenBlender-Code geschieht - unter Verwendung eines statischen Codierers / Decodierers in einer Umgebung mit mehreren Threads).
Persönlich verwende ich gerne Convenience- Methoden (gegenüber den allgemeineren Codierungs- / Decodierungsmethoden), da sie die Belastung verringern, indem sie alle Schritte unter der Abdeckung ausführen.
ZenBlender und Adamski haben in ihren Kommentaren bereits mehrere Möglichkeiten vorgeschlagen, dies sicher zu tun. Listen Sie sie alle hier auf:
PS
Java Docs Referenzen:
quelle