String in einen OutputStream schreiben - welche Klassen verwenden?

DarthShader

Erfahrenes Mitglied
Hallo,

ich komme immer wieder ins Schleudern, wenn es um diese ganzen verschiedenen IO Klassen geht, wie PrintWriter, die Buffered Stream Klassen etc... oft weiß ich nicht, welche Klasse ich am besten einsetze.

Ich habe nun die Situation, dass es eine Methode gibt, innerhalb derer ich einen String in den übergebenen OutputStream schreiben möchte.

Das sieht folgendermaßen aus:

Java:
public void write( OutputStream out )
{
	PrintWriter pw = new PrintWriter( out );
	pw.println( "Hello World" );
	pw.flush();
}

Mir stellt sich nun die Frage, warum ich pw.flush() machen muss (in einem Testprogramm ist der übergebene OutputStram "System.out" und ich sehe "Hello World" erst auf der Konsole, wenn ich pw.flush() aufrufe). Ist denn der PrintWriter auch gepuffert, obwohl es dafür extra BufferedXXX Klassen gibt?

Ist der code oben denn gut so? Oder sollte ich lieber einen BufferedWriter für soetwas verwenden, wie folgt:

Java:
public void write( OutputStream out )
{
	BufferedWriter bw = new BufferedWriter( new PrintWriter(out ) );
	
	try
	{
		bw.write( "Hello World!" );
		bw.flush();
	}
	catch ( IOException e ) { e.printStackTrace(); }
}

Hier habe ich den PrintWriter durch einen BufferedWriter gewrappt. Um die Ausgabe auf der Konsole zu sehen, muss ich wieder bw.flush() machen. Das kann ich aber verstehen, der die Ausgabe wird ja gepuffert. Aber warum muss ich denn bei einem BufferedWriter eine IOException abfangen, und beim PrintWriter nicht?


Ist das 2. Codebeispiel besser, oder gibt es einen noch anderen Weg, quasi eine Best Practice? Wie würdet Ihr die Geschichte lösen?


Danke für Eure Hilfe!
 
Hallo,

also nach meinem Kenntnisstand kann man sich beim PrintWriter in der Tat die flush()-Anweisung sparen (im Gegensatz zum BufferedWriter).

Aber verstehe ich das jetzt richtig, dass es ohne das flush() im ersten Beispiel gar nicht funktioniert

tschüss
Klaus
 
Zuletzt bearbeitet:
Also das zu Beantworten warum Flush beim PrintWriter gibt der Sourcecode sehr guten Aufschluß

Code:
...
    public PrintWriter(OutputStream out) {
	this(out, false);
    }

    /**
     * Creates a new PrintWriter from an existing OutputStream.  This
     * convenience constructor creates the necessary intermediate
     * OutputStreamWriter, which will convert characters into bytes using the
     * default character encoding.
     *
     * @param  out        An output stream
     * @param  autoFlush  A boolean; if true, the <tt>println</tt>,
     *                    <tt>printf</tt>, or <tt>format</tt> methods will
     *                    flush the output buffer
     *
     * @see java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream)
     */
    public PrintWriter(OutputStream out, boolean autoFlush) {
	this(new BufferedWriter(new OutputStreamWriter(out)), autoFlush);
	// save print stream for error propagation
	if (out instanceof java.io.PrintStream) { 
	    psOut = (PrintStream) out;
	}
    }

...

Der Konstruktor, wie zu erkennen, verwendet bereits einen BufferedWriter. In der Einfachen Variante ohne Autoflush wird ein false als Default genommen!

Takidoso

PS: Die IO-Klassen sind in mancher Beziehung heftig viele. So ein Vererbungsbaum, den ich mal irgendwo in einem Buch gesehen hatte half meinem Verständnis in der ein oder anderen Weise gut auf die Sprünge.
 
Hallo Takidoso,

ein guter Hinweis - Danke !!
Das war mir so auch nicht klar :rolleyes:

Habe eben mal die Sourcen der Projekte durchsucht, die ich hier vor einiger Zeit übernommen habe. Es gab nur eine einzige Stelle - und da wurde dann wohl auch genau dieses Autoflush verwendet .....

tschüss
Klaus
 
Also Ich würde das erste Codebeispiel bevorzugen, da ich dem Sourcecode zur Folge im 2. Beispiel IMHO einen doppelten Puffer haben müsste, oder?

Ja, das denke ich auch. Ich baue da im 2. Beispiel einen Buffer drum, aber der PritnWriter selbst baut auch nochmal einen Buffer, das ist sicher überflüssig. Das autoFlush habe ich total übersehen, danke für den Hinweis :)

Ich bin mir allgemein recht unsicher, was ich genau für IO Klassen nehme. Immer wenn es im Input/Ouput geht, sehe ich mich durch die API suchen, was ich nun für Klassen nehme. Kennt vielleicht jemand eine Seite, wo genau diese Thematik mal aufgedröselt ist?

Danke
 
Zurück