Wie kann eine Datei am Effizientesten geschrieben werden?

Schnoogle

Mitglied
Hallo,

ich muss eine CSV-Datei mit dem Encoding UTF-8 erstellen.

Hierfür muss ich OutputStreamWriter verwenden.

In der Java-API wird zum Einen empfohlen einen OutputStreamWriter in einem BufferedWriter zu kapseln, damit nicht bei jedem Methodenaufruf die Konvertierung durchgeführt werden und zum Anderen wird empfohlen nicht direkt in einen FileWriter bzw. FileOutputStream zu schreiben sondern die zu schreibenden Daten zu puffern.

Welche Kombination an Writer- und Stream-Implementierungen (Vorschlag A oder Vorschlag B) ist denn für meinen Anwendungsfall sinnvoller?

Vorschlag A:

Code:
final FileOutputStream fileOutputStream = new FileOutputStream(file);
final OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "UTF-8");
final BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);

Vorschlag B:

Code:
final FileOutputStream fileOutputStream = new FileOutputStream(file);
final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
final OutputStreamWriter outputStreamWriter = new OutputStreamWriter(bufferedOutputStream, "UTF-8");
final BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
 
Hi

Kurzfassung: Schwer zu sagen, aber die Unterschiede sind so minimal...
wenns einen stört ist man bei C vermutlich besser aufgehoben.

Vorneweg: Die eine effizienteste Lösung hängt von sehr vielen Details ab (zB. was, wieviel, mit wievielen Methodenaufrufen geschrieben wird; Verhältnis Festplatten/CPU-Leistung, sonstige Auslastung vom System, Betriebssystem, Java-Implementierung...), und Java ist auch nicht der ideale Ansatzpunkt ... jedenfalls kann dir niemand garantieren, dass es nichts Besseres gibt, nur Vermutungen machen.

Falls interessant: Die Javadocs untertreiben sehr, warum Buffering Sinn macht.
a) Verallgemeinert von der Aussage über Konvertierungen: Doppelt so viel Daten zu schreiben dauert (in der Theorie) natürlich doppelt so lang, aber jeder Aufruf von write() oder Ähnlichem hat auch einen datenunabhängigen zusätzlichen Zeitverbrauch. Im Extremfall gehen die Daten von einem Aufruf alle Ebenen von Java, C, dem Betriebssystem und der Hardware runter, und das verbraucht Prozessorleistung und damit Zeit. Das für jedes Byte extra zu machen oder nur einmal für 1Million Byte macht natürlich einen Unterschied. Entweder man passt selber auf, wie und wie oft man Sachen schreibt, oder man verwendet eben einen Buffer, der kleine Writes zusammensammelt und ab und zu dafür große rausschickt.
b) Festplatten können mit einzelnen Byte nicht wirklich umgehen. Übliche Größen, die sie haben wollen, sind 512 (oder auch 4096) Byte, und ein Byte allein hinzugeben dauert genau so lang wie 512 (wenn hintereinander in der selben Datei). Selbe Abhilfe wie oben, Daten zuerst sammeln und in passenden Blöcken dann zur Platte. Auf Java bezogen ist das Plattenproblem aber nicht so wichtig, weil das Betriebssystem selber auch buffert (wenn man will auch pro offener Datei abschaltbar, um sich selber mit der Blockung herumzuärgern, aber nicht möglich in Java)

Zurück zu Java:

Gar kein Buffeirng wäre nicht gut, weils mit doch besser ist und es ja nciht weh tut, es einzusetzen.
Das OS buffert zwar auch, aber eben einige Ebenen drunter erst. Das ständige "runterschicken" erspart man sich so.

Nur BufferedOutputStream würde dazu führen, bei jedem Schreiben die Konvertierung usw. zu machen. Ich denk ja nicht, dass der Konvertierungsteil besser wird, wenn es mehr Daten auf einmal sind, aber wenn die DOks das sagen...

Nur BufferedWriter hat das Problem, dass die Konvertierung drunter die Byteanzahl
verändert und dadurch wieder nicht in Idealgrößen weitergeschickt wird.

Beide zusammen verbrauchen viel Speicher, und je nachdem wie man schreibt ist es evt. gar nicht besser als eins allein.

... Letztendlich müsste man das messen (nicht irgendwie, auch da sind Sachen zu beachten)
Aber wie gesagt, solange man nicht absichtlich immer Einzelbyte schreibt und immer danach
flush() aufruf ist der Unterschied ist vernachlässigbar. Wenn man besser werden will
machen eine SSD, ein besserer Rechner gesamt und ein Umstieg zu C mehr aus.
 
Zurück