2009-05-25 5 views
34

In einem Java-Programm (Java 1.5) zu spülen, habe ich eine BufferedWriter, die einen Filewriter Wraps, und ich rufe write() viele, viele Male ... Die resultierende Datei ist ziemlich groß ...Wenn ein BufferedWriter

Unter den Zeilen dieser Datei sind einige davon unvollständig ...

Muss ich Flush jedes Mal aufrufen, wenn ich etwas schreibe (aber ich vermute, es wäre ineffizient) oder eine andere Methode von BufferedWriter verwenden oder eine andere Klasse verwenden ...?

(Da ich eine zillion Zeilen zu schreiben habe, möchte ich etwas ziemlich effizient haben.) Was wäre der ideale "Spülung" Moment? (Wenn ich erreichen, die Kapazität des BufferedWriter) ...

Init:

try { 
    analysisOutput = new BufferedWriter(new FileWriter(
     "analysisResults", true)); 
    analysisOutput.newLine(); 
    analysisOutput.write("Processing File " + fileName + "\n"); 
} 
catch (FileNotFoundException ex) { 
    ex.printStackTrace(); 
} 
catch (IOException ex) { 
    ex.printStackTrace(); 
} 

Schreiben:

private void printAfterInfo(String toBeMoved,HashMap<String, Boolean> afterMap, Location location) 
    throws IOException { 
    if(afterMap != null) { 
     for (Map.Entry<String, Boolean> map : afterMap.entrySet()) { 
     if (toBeMoved == "Condition") { 
      if (1 <= DEBUG) 
      System.out.println("###" + toBeMoved + " " + location + " " 
       + conditionalDefs.get(conditionalDefs.size() - 1) 
       + " After " + map.getKey() + " " 
       + map.getValue() + "\n"); 

      analysisOutput.write("###" + toBeMoved + " " + location + " " 
       + conditionalDefs.get(conditionalDefs.size() - 1) 
       + " After " + map.getKey() + " " + map.getValue() 
       + "\n"); 
     } else { 
      if (1 <= DEBUG) 
      System.out.println("###" + toBeMoved + " " + location + " " 
       + map.getKey() + " After " 
       + map.getValue() + "\n"); 
      if (conditionalDefs.size() > 0) 
      analysisOutput.write("###" + toBeMoved + " " + location + " " 
       + conditionalDefs.get(conditionalDefs.size() - 1) + " " 
       + map.getKey() + " After " + map.getValue() 
       + "\n"); 
      else 
      analysisOutput.write("###" + toBeMoved + " " + location + " " + map.getKey() + " After " + map.getValue() + "\n"); 


     } 
     } 
    } 

Ich habe gerade herausgefunden, dass die Linien, die unvollständig sind, sind die, die gerade vor „Verarbeitungsdatei“ ... so kommt es, wenn ich von einer Datei bin Schale, dass ich zu einem anderen zu analysieren ...

Schliessung:

dispatch(unit); 

try { 
    if (analysisOutput != null) { 
    printFileInfo(); 
    analysisOutput.close(); 
    } 
} 
catch (IOException ex) { 
    ex.printStackTrace(); 
} 

Manchmal sind die Informationen, die von printFileInfo ausgedruckt erscheint nicht in der Ergebnisdatei ...

+0

sind unvollständig, haben Sie mehrere Threads schreiben? IIRC a BufferedWriter ist NICHT threadsicher, das könnte eine Erklärung sein, aber es muss NICHT "manuell gespült" werden, um mehr Platz zu schaffen, es kümmert sich darum. –

+0

Wenn Sie nicht sicher sind, ob Ihre Frage klar ist, geben Sie vielleicht ein Codebeispiel oder ein Ausgabeprobe an, das verdeutlicht. –

+0

Es ist tatsächlich Thread-sicher (obwohl Writer-Dekoratoren Probleme haben, sich darüber zu einigen, welches Objekt zu sperren ist). –

Antwort

74

Die BufferedWriter wird bereits gespült, wenn sie ihren Puffer füllt. Aus der Dokumentation von BufferedWriter.write:

Normalerweise Diese Methode speichert Zeichen aus der gegebenen Gruppe in diesen Puffer Stream, die Puffer zu dem darunter liegenden Strom nach Bedarf Spülung.

(Hervorhebung von mir.)

Der Punkt BufferedWriter ist im Grunde viele kleine schreibt in weit weniger groß schreibt zu konsolidieren, so dass in der Regel effizienter (aber mehr Schmerz zu Code für). Sie sollten nichts Besonderes tun müssen, damit es richtig funktioniert, abgesehen davon, dass Sie es spülen, wenn Sie fertig sind mit ihm - und Aufruf close() wird dies tun und bündig/schließen Sie den zugrunde liegenden Schreiber sowieso.

Mit anderen Worten, entspannen - einfach schreiben, schreiben, schreiben und schließen :) Die einzige Zeit, die Sie normalerweise flush manuell aufrufen müssen, ist, wenn Sie wirklich, wirklich die Daten jetzt auf der Festplatte benötigen. (Wenn Sie zum Beispiel einen Perpetual Logger haben, möchten Sie ihn vielleicht so oft löschen, dass derjenige, der die Logs liest, nicht warten muss, bis der Puffer voll ist, bevor er neue Log-Einträge sehen kann.)

+0

Getestet und genehmigt. Geschrieben 10Mb Zahlen Zeile für Zeile: Spülung nach jeder Zeile schreiben - dauert 7 Sekunden, ohne zu spülen - 4 Sekunden. –

8

Die ideale Spülung Moment ist, wenn Sie ein anderes Programm benötigen Sie die Datei zu lesen, die Daten zu sehen, die geschrieben worden ist, bevor die Datei ist geschlossen. In vielen Fällen ist das nie.

+0

auch wenn der BufferedWriter groß ist ... muss ich das nicht in einem Zwischenstadium tun? – LB40

+0

Wenn der Puffer voll ist, schreibt er seinen Inhalt auf die Festplatte. Die BufferedWriter-API wurde als Ersatz für einen FileWriter entwickelt, mit der Ausnahme, dass Daten verbraucht werden, bevor die Datei geschlossen wird. – Dave