2013-04-03 5 views
5

Ich möchte in eine Steckdose schreiben. Aus der Lektüre über die Netzwerk-IO, so scheint es mir, dass der optimale Weg zu schreiben, um es so etwas wie dies zu tun ist:Ist es Overkill, BufferedWriter und BufferedOutputStream zusammen zu verwenden?

OutputStream outs=null; 
BufferedWriter out=null; 
out = 
    new BufferedWriter(
    new OutputStreamWriter(new BufferedOutputStream(outs),"UTF-8")); 

Die BufferedWriter den Eingang die OutputStreamWriter Puffer würde, die empfohlen wird, weil es den Schreiber verhindert Starten des Encoders für jedes Zeichen.

Die BufferedOutputStream würde dann die Bytes von Writer puffern, um zu vermeiden, dass ein Byte nach dem anderen potenziell in das Netzwerk eingefügt wird.

Es sieht ein bisschen wie Overkill aus, aber es scheint alles wie es hilft? Für jede Hilfe dankbar ..

EDIT: Von der javadoc auf OutputStreamWriter:

Jeder Aufruf einer Methode write() bewirkt, dass die Codierung Wandler auf der gegebenen Stelle (n) aufgerufen werden. Die resultierenden Bytes werden in einem Puffer gesammelt, bevor sie in den zugrundeliegenden Ausgabestrom geschrieben werden. Die Größe dieses Puffers kann angegeben werden, ist aber standardmäßig groß genug für die meisten Zwecke. Beachten Sie, dass die an die write() -Methode übergebenen Zeichen nicht gepuffert sind.

Um höchste Effizienz zu erzielen, sollten Sie einen OutputStreamWriter in einen BufferedWriter einfügen, um häufige Konverteraufrufe zu vermeiden. Zum Beispiel:

Writer out = new BufferedWriter(new OutputStreamWriter(System.out)); 

Antwort

1

Die BufferedWriter die Eingabe in den Output Puffer würde, was empfohlen wird, weil es die Schreiber von der Inbetriebnahme des Gebers für jedes Zeichen verhindert.

Von wem empfohlen und in welchem ​​Kontext? Was meinst du mit "den Encoder starten"? Schreibst du dem Verfasser immer nur ein Zeichen? (Wir wissen nicht viel darüber, wie Sie den Schriftsteller verwenden ... so wichtig sein könnte.)

Die BufferedOutputStream würde dann den Bytes aus der Writer-Puffer ein Byte zu einem Zeitpunkt, zu vermeiden, dass möglicherweise auf das Netzwerk.

Was lässt Sie denken, dass es ein Byte zu einem Zeitpunkt schreiben würde? Ich denke, es ist sehr unwahrscheinlich, dass OutputStreamWriter ein Byte zu einem Zeitpunkt auf dem zugrunde liegenden Writer schreiben wird, es sei denn, Sie schreiben wirklich ein Zeichen nach dem anderen.

Darüber hinaus würde ich erwarten, dass der Netzwerk-Ausgabestream etwas wie Nagle's algorithm verwendet, um das Senden von Single-Byte-Paketen zu vermeiden.

Wie immer mit der Optimierung, sollten Sie es auf Beweise basieren ... Haben Sie Tests mit und ohne diese Pufferschichten durchgeführt?

EDIT: Nur um zu verdeutlichen, sage ich nicht die Pufferklassen sind nutzlos. In einigen Fällen sind sie absolut der richtige Weg zu gehen. Ich sage nur, dass mit alle Optimierung, sollten sie nicht blind verwendet werden. Sie sollten überlegen, was Sie optimieren möchten (Prozessorauslastung, Speichernutzung, Netzwerknutzung usw.) und messen.Es gibt viele Faktoren, die hier eine Rolle spielen - nicht zuletzt das Schreibmuster. Wenn Sie bereits "chunky" schreiben - große Blöcke von Zeichendaten schreiben - dann haben die Puffer einen relativ geringen Einfluss. Wenn Sie dem Verfasser tatsächlich jeweils ein Zeichen schreiben, wären sie bedeutender.

+0

Vielen Dank für Ihre Antwort. Aus dem Javadoc in OutputStreamWriter: "Jeder Aufruf einer write() -Methode bewirkt, dass der Codierungskonverter für die angegebenen Zeichen aufgerufen wird. Die resultierenden Bytes werden in einem Puffer gespeichert, bevor sie in den zugrunde liegenden Ausgabestream geschrieben werden Dieser Puffer kann angegeben werden, ist aber standardmäßig für die meisten Zwecke groß genug. Beachten Sie, dass die an die write() -Methode übergebenen Zeichen nicht gepuffert sind. Um höchste Effizienz zu erzielen, sollten Sie einen OutputStreamWriter in einen BufferedWriter einfügen, um häufige Konverteraufrufe zu vermeiden . " Ganzes Zitat in OP bearbeiten – Bruce

+0

@Bruce: * Überlegen Sie *, sicher. Das ist nicht das Gleiche wie * empfehle *. Ich würde es testen. Ich wäre sehr überrascht zu sehen, dass es in den meisten Fällen einen signifikanten Unterschied macht. –

+0

Danke für Ihre nützlichen Antworten. Ja, ich sollte es testen. Es ist tatsächlich als Teil eines Programmiertests, den ich für ein Interview gemacht habe, und ich wollte wissen, was für eine standardmäßige korrekte Lösung wäre, oder zumindest eine, die nicht offensichtlich falsch ist. – Bruce

7

Der Zweck der Buffered * -Klassen besteht darin, kleine Schreiboperationen in eine größere zusammenzufassen, wodurch die Anzahl der Systemaufrufe reduziert und der Durchsatz erhöht wird.

Da ein BufferedWriter bereits Schreibvorgänge in einem Puffer sammelt, die Zeichen im Puffer in einen anderen Puffer konvertiert und diesen Puffer in einem einzigen Vorgang in den zugrunde liegenden OutputStream schreibt, wird der OutputStream bereits mit großen Schreibvorgängen aufgerufen. Daher findet ein BufferedOutputStream nichts zu kombinieren und ist einfach redundant.

Nebenbei kann das gleiche für den BufferedWriter gelten: Pufferung wird nur helfen, wenn der Schreiber nur wenige Zeichen auf einmal übergeben wird. Wenn Sie wissen, dass der Aufrufer nur große Strings schreibt, findet der BufferedWriter nichts zusammen und ist auch redundant.

+1

Danke für Ihre Antwort. Das verdeutlicht viel. Ich denke, ich hatte das Gefühl, dass es eine schlechte Form war, die Pufferung wegzulassen, aber was Sie sagen, macht sehr viel Sinn. – Bruce

1

Ja, es ist Overkill. Von Javadoc for OutputStreamWriter: "Jeder Aufruf einer write() - Methode bewirkt, dass der Codierungskonverter für die angegebenen Zeichen aufgerufen wird. Die resultierenden Bytes werden in einem Puffer gespeichert, bevor sie in den zugrunde liegenden Ausgabedatenstrom geschrieben werden."

+0

@ downvoter Sie streiten sich hier mit dem Javadoc. Welcher Teil ist genau falsch? – EJP

+0

(Ich bin nicht der Downvoter!) Ich denke, das ist eine perfekte, prägnante Antwort! Es ist klar, dass wir durch _wrapping_ mit einem Buffer sicherstellen, dass der Encoder nur ausgelöst wird, wenn eine Ansammlung von Zeichen vorhanden ist, und da er einen internen Puffer hat, löst er nur zugrunde liegende Schreibvorgänge aus, wenn dieser Puffer voll ist. – SusanW

Verwandte Themen