Ich habe eine kleine Frage zu Java IO. Und zwar möchte ich den Objekt Inhalt einer Liste in einer Datei speicher (Klartext). Dafür habe ich folgenden Code:
Normalerweise soll man einen Stream ja immer schließen, jedoch ist das hier nicht möglich, da sonst der PrintStream auch den OutputStream schließt. Deshalb wollte ich fragen, ob es in einer solchen Situation in Ordnung ist den PrintStream nicht zu schließen, oder ob das einfach eine grundsätzlich schlechte Lösung ist.
Wenn Du in der Methode druckeDaten doch eh nur this übergibst, warum nicht so? Warum muss das Medium den PrintStream und Outputstream überhaupt kennen?
Als erstes zu dem Code von @sascha-sphw:
a) PrintStream hat einen Konstruktor, der ein File nimmt, FileOutputStream braucht es nicht.
b) close() macht auch ein Flush, daher ist ein expliziter flush Aufruf nicht notwendig.
Java:
publicvoidsafeInTxt(){try(PrintStream ps =newPrintStream(newFile("Test"))){for(Medium medium : medien){
ps.println(medium);}}catch(IOException e){//TODO}}
Bezüglich der Fragen von @RawRaven:
a) Du schliesst nur Dinge, die Dir "gehören". Etwas, das dir nur übergeben wird, hast Du in der Regel nicht zu schließen. Daher ja: Du hast den Stream, den Du als Parameter bekommen hast, nicht zu schließen.
b) PrintStream implementiert AutoClosable. Und Du erzeugst die Instanz. Daher sollte diese Instanz, die Dir gehört, tatsächlich geschlossen werden.
Wie Du sehr gut erkannt hast, beißen sich diese Regeln. Daher ist hier in der Regel eine Änderung notwendig. Also z.B. diesen als Parameter bereits angeben. (Denn Dein Code erfordert diesen) oder eben darauf verzichten.
Dann wäre durchaus denkbar, den PrintStream nicht zu schließen und nur ein flush aufzurufen. Aber das ist etwas, das ich nicht gut finde.
Daher wäre es sinnvoll, sich auf die Möglichkeiten vom OutputStream zu beschränken.
-> OutputStream hat z.B. ein write(byte[])
Damit ist folgendes möglich:
-> Instanz per toString() in einen String umwandeln.
-> Dann per getBytes() oder getBytes(String charset) das Byte Array holen
-> Dieses dann in den Stream schreiben.
Normalerweise soll man einen Stream ja immer schließen, jedoch ist das hier nicht möglich, da sonst der PrintStream auch den OutputStream schließt. Deshalb wollte ich fragen, ob es in einer solchen Situation in Ordnung ist den PrintStream nicht zu schließen, oder ob das einfach eine grundsätzlich schlechte Lösung ist.
Die Methode PrintStream#close schliesst auch den im Konstruktor übergebenen/erzeugten OutputStream.
Die beste Praxis ist IMHO den letzten (top level) Stream zu schliessen.
Damit wird auch jeder Buffer in der Hierarchie ge-flusht.
Natürlich Schliessen auf der richtigen Ebene, also auf der Ebene der Erzeugung, nicht in untergeordnet aufgerufenen Methoden.
Natürlich ist diese Lösung etwas starr, so wie Konstruktor und Destruktor für eine lokale Variable in C++.
Wenn man wünscht, so wie ein Java-Objekt, es irgendwo zu erzeugen und irgendwo (mehrfach) zu referenzieren, eventuell in verschiedenen Threads, kann man dies so nicht machen.
Aber im Gegensatz zu einem Java-Speicher-Objekt, das einfach verschwindet, muss es beim Stream ein Schliessen geben und man muss sich auf ein Geschlossen-Sein verlassen können, zum Beispiel wenn man in eine Datei unter einem temporären Namen schreibt und diese nach verlässlichem Schreiben zum endgültigen Namen umbenennt.