写入大文件时,FileOutputStream.close非常慢

sim*_*mon 5 java fileoutputstream

我有一个方法,使用此代码通过TCP套接字接收文件:

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();
Run Code Online (Sandbox Code Playgroud)

FileOutputStream.close在接收大文件时花了很长时间,为什么呢?正如你所看到的那样,我正在每个收到的大块上冲洗流.

Pet*_*rey 4

根据操作系统的不同,flush()除了强制将数据写入操作系统之外,什么也不做。对于 FileOutputStream,write() 将所有数据传递到操作系统,因此 flash() 不执行任何操作。其中close()可以确保文件实际写入磁盘(或不取决于操作系统)。可以在写入数据时查看磁盘是否还处于繁忙状态。

500 MB 的文件需要 30 秒,意味着您正在以 17 MB/s 的速度写入。这听起来像是一个非常慢的磁盘或文件位于网络共享/驱动器上。


你可以试试这个

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);
Run Code Online (Sandbox Code Playgroud)

印刷

Took 0.116 seconds to write 500,006,912 bytes
Took 0.002 seconds to close
Run Code Online (Sandbox Code Playgroud)

从速度可以看出,在这个系统上,即使关闭也不会写入数据。即驱动器不是那么快。

  • `flush()` 对 `FileOutputStream` 不执行任何操作。它仅对缓冲流有用。 (3认同)
  • 不,“FileOutputStream.close”不能保证所有字节都实际写入磁盘。但您可以保证所有字节都写入操作系统缓冲区。如果操作系统崩溃,例如电源故障,您已经从 close() 返回的 FileOutputStream 可能会丢失数据。 (2认同)