当前位置: 首页 > 面试题库 >

写入大文件时,FileOutputStream.close确实很慢

辛健
2023-03-14
问题内容

我有一个使用此代码通过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();

接收大文件时,FileOutputStream.close会花费很长时间,这是为什么呢?如您所见,我正在每个接收到的块上刷新流。


问题答案:

根据操作系统的不同,flush()仅需强制将数据写入操作系统即可。对于FileOutputStream,write()将所有数据传递给OS,因此flush()不会执行任何操作。凡为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);

版画

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

从速度上您可以看到,即使在关闭状态下,该系统也无法写入数据。即驱动器不是那么快。



 类似资料:
  • 问题内容: 我正在尝试将大的ResulSet(〜1mm行)写入单个文件。在Java 1.6中,有没有一种首选/有效的方法来做到这一点? 问题答案: 这取决于所使用的JDBC驱动程序。您需要指示JDBC驱动程序 不要事先将其全部加载到Java内存中,而应在每次调用时逐行加载。然后,在循环内部,您需要 立即 将数据写入文件,而不是将其保存在文件中。 不清楚您使用的是哪种JDBC驱动程序,但是例如,可以

  • 我存储用户收藏夹到json文件,但我得到以下错误: 未处理的异常:类型“\u InternalLinkedHashMap” 我将以下数据添加到文件中: 代码是: 我很困惑,不知道如何解决这个问题。

  • 问题内容: 我正在不同的机器上运行多个进程,这些进程需要读/写到共享的XML文件,为此我正在使用和(虽然我知道数据库将是一种更有效的方法,但由于项目限制,这种方法不可行) 。 要更改XML文件,相关过程首先创建一个专用锁定的通道,该通道用于读取文件,然后尝试在关闭通道之前重用相同的通道来写入新版本。这样锁就永远不会掉下来。但是,问题是,即使我从未明确关闭通道,尝试写入结果时也会得到提示。我怀疑那行

  • 问题内容: 我必须阅读tomcat日志文件,并在一段时间(例如:一个小时)后再次读取该文件(仅针对新添加的内容),因此我创建了RandomAccessFile来记录我完成的最后一个位置并使用BufferedReader.readLine()方法。 但是,我发现有时我无法读取文件的整行。 例如,tomcat正在尝试编写以下内容(仅作为示例): 192.168.0.0本地主机/index.html .

  • 我正在尝试创建许多文件,作为用户的一个功能。例如,我可能会编写一个应用程序,为他们过去几周听的每首歌创建一个文件(例如,一个带有歌词的文本文件)。我不能让用户为我生成的每个文件选择目录和文件名,这将花费他们数小时的时间。用户应该可以从其他应用程序访问这些文档。 在Android11中,存储访问框架似乎没有什么用处。我注意到最初有两个有趣的选项: 创建一个新文件(该文件创建启动用户与之交互的活动,以

  • 我正在阅读一个用一些分隔符分隔的文本文件。 我的文本文件内容示例 Avc def efg JKSJD 1 2 3 5 3 4 6 0 每次调用createRow和createCell时是否都会创建新对象? 如果是,有什么替代方案?。如何以更好的性能将大数据写入excel?