2016-04-23 15 views
6

Ich muss einen Strom von char in einen Strom von byte s konvertieren, d. H. Ich brauche einen Adapter von einer java.io.Writer Schnittstelle zu einem java.io.OutputStream, unterstützt alle gültigen Charset, die ich als Konfigurationsparameter haben werde.Existiert ein OutputStreamWriter ohne Pufferung?

Die java.io.OutputStreamWriter Klasse hat jedoch ein verstecktes Geheimnis: das sun.nio.cs.StreamEncoder Objekt, das es zu unterhalb delegiert, erstellt einen 8192 Byte (8 KB) Puffer, auch wenn Sie es nicht fragen.

Das Problem ist, an der OutputStream Ende I einen Wrapper eingefügt haben, die geschrieben werden muss die Menge der Bytes zählen, so dass sie sofort die Ausführung des Quellsystems stoppt, sobald eine bestimmte Menge von Bytes ausgegeben wurde. Und wenn OutputStreamWriter einen 8K Puffer erstellt, werde ich einfach über die Menge an erzeugten Bytes zu spät benachrichtigt, weil sie nur meinen Zähler erreichen werden, wenn der Puffer Spülen (so wird es bereits mehr als 8.000 bereits generierte Bytes sein wartet auf mich im OutputStreamWriter Puffer).

Die Frage ist also, ist es überall in der Java eine Writer Laufzeit ->OutputStream Brücke, die ungepufferte laufen kann?

Ich würde wirklich, wirklich hasse zu haben, diese selbst schreiben: (...

HINWEIS: Schlagen flush() auf die OutputStreamWriter für jeden Schreib ist keine gültige Alternative Das bringt ein. große Leistungseinbuße (es gibt einen synchronized Block an der StreamEncoder beteiligt)

ANMERKUNG 2. ich verstehe es notwendig sein könnte, ein kleines Zeichen Überlauf an der Brücke, um Surrogate zu berechnen zu halten es ist nicht, dass ich muss. Stoppen Sie den Executor Ion des Quellsystems in dem Moment, in dem es erzeugt das n-te Byte (das wäre nicht möglich, gegeben Bytes können zu mir in Form eines größeren byte[] in einem write Aufruf kommen). Aber ich muss es stoppen asap, und warten auf einen 8K, 2K oder sogar 200-Byte-Puffer zu spülen wäre einfach zu spät.

+0

es wohl * kann * nicht vollständig sein ungepuffert - wenn Sie 'write' nur mit der ersten Hälfte eines Ersatzpaares aufrufen, müsste der Schreiber * für die meisten Codierungen * das * speichern * und auf das zweite Zeichen warten, bevor er etwas schreibt. –

+0

Nun ja, das verstehe ich natürlich. Aber es gibt einen Unterschied zwischen ein paar gepufferten Zeichen, die benötigt werden, um ein Ersatzpaar und einen 8K Puffer zu berechnen ... –

+0

Ich glaube nicht, dass es "natürlich" dort gibt - ich vermute, dass viele Leser annehmen, dass Sie überhaupt keine Pufferung meinen, und dass Sie möglicherweise keine Ersatzpaare kennen. Ich schlage vor, Sie bearbeiten die Frage, um das zu klären. (Wäre es "zu spät", wenn der erste Aufruf von 'write' zum Beispiel die Ausführung nicht stoppt?) –

Antwort

7

Wie Sie bereits festgestellt haben, hat die StreamEncoder von OutputStreamWriter eine Puffergröße von 8KB verwendet und es gibt keine Schnittstelle, um diese Größe zu ändern.

Aber der folgende Code-Schnipsel gibt Ihnen eine Möglichkeit, ein Writer für ein OutputStream, die intern auch ein StreamEncoder verwendet erhalten hat, aber jetzt eine benutzerdefinierte Puffergröße:

String charSetName = ... 
CharsetEncoder encoder = Charset.forName(charSetName).newEncoder(); 

OutputStream out = ... 
int bufferSize = ... 

WritableByteChannel channel = Channels.newChannel(out); 
Writer writer = Channels.newWriter(channel, encoder, bufferSize); 
+0

Ich kann Ihnen dafür nicht genügend Punkte geben. Es funktioniert wie ein Zauber, vielen Dank. Die einzige Sache, um die ich mir etwas Sorgen mache, ist, dass die Spezifikation diese 'pufferSize' als * minimale * Puffergröße definiert. Aber ich sehe, dass die Standardimplementierung bei 'sun.nio.cs.StreamEncoder' diese einfach als feste Größe verwendet, also sollte das genügen. Danke noch einmal. –