5 Stimmen

FileOutputStream.close ist sehr langsam beim Schreiben großer Dateien

Ich habe eine Methode, die eine Datei über einen TCP-Socket mit diesem Code empfängt:

FileOutputStream fileStream = new FileOutputStream(filename.getName());
while (totalRead < size) {
    if (size - totalRead > CHUNKSIZE) {
        read = getInputStream().read(buffer, 0, CHUNKSIZE);
    } else {
        read = getInputStream().read(buffer, 0, size - totalRead);
    }
    totalRead += read;
    fileStream.write(buffer, 0, read);
    fileStream.flush();

    if (System.currentTimeMillis() > nextPrint) {
        nextPrint += 1000;
        int speed = (int) (totalRead / (System.currentTimeMillis() - startTime));
        double procent = ((double)totalRead / size) * 100;
        gui.setStatus("Reciving: " + filename + " at " + speed + " kb/s, " + procent + "% complete");
    }
}
gui.setStatus("Reciving: " + filename + " complete.");
fileStream.close();

FileOutputStream.close braucht beim Empfang großer Dateien sehr lange, woran liegt das? Wie Sie sehen, spüle ich den Stream bei jedem empfangenen Chunk

4voto

Peter Lawrey Punkte 511323

Je nach Betriebssystem, flush() tut nichts weiter, als das Schreiben der Daten in das Betriebssystem zu erzwingen. Im Fall von FileOutputStream übergibt write() alle Daten an das Betriebssystem, so dass flush() nichts bewirkt. Wobei als close() kann sicherstellen, dass die Datei tatsächlich auf die Festplatte geschrieben wird (oder nicht, je nach Betriebssystem). Sie können überprüfen, ob die Festplatte beim Schreiben der Daten noch belegt ist.

Eine 500-MB-Datei, die 30 Sekunden braucht, bedeutet, dass Sie 17 MB/s schreiben. Das klingt nach einer sehr langsamen Festplatte oder danach, dass sich die Datei auf einer Netzwerkfreigabe/einem Netzlaufwerk befindet.


Das können Sie versuchen

File file = File.createTempFile("deleteme", "dat"); // put your file here.
FileOutputStream fos = new FileOutputStream(file);
long start = System.nanoTime();
byte[] bytes = new byte[32 * 1024];
for (long l = 0; l < 500 * 1000 * 1000; l += bytes.length)
    fos.write(bytes);
long mid = System.nanoTime();
System.out.printf("Took %.3f seconds to write %,d bytes%n", (mid - start) / 1e9, file.length());
fos.close();
long end = System.nanoTime();
System.out.printf("Took %.3f seconds to close%n", (end - mid) / 1e9);

druckt

Took 0.116 seconds to write 500,006,912 bytes
Took 0.002 seconds to close

Anhand der Geschwindigkeit kann man erkennen, dass das System die Daten nicht einmal in der Nähe schreibt, d.h. das Laufwerk ist nicht so schnell.

1voto

What Punkte 11

Das Gleiche habe ich bei der Verwendung von Filestream gesehen. Was ich dort fand, war, wenn Sie die Datei als readwrite öffnen, es zwischengespeichert alles und nicht schreiben, bis Sie schließen oder entsorgen. Flush hat nicht geschrieben. Wenn jedoch die Schreibvorgänge die Größe der Datei überschreiten, wird automatisch geleert.

Öffnen als einfaches Schreiben mit Autoflush bei jedem Schreiben.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X