【问题标题】:FileInput/OutputStream versus FileChannels -- which gives better performanceFileInput/OutputStream 与 FileChannels - 提供更好的性能
【发布时间】:2011-07-05 20:21:30
【问题描述】:

我正在编写一个程序,该程序必须从一个文件夹复制大量但不是大量的数据(一次在几十张照片的范围内)。最初我使用java.io.FileOutputStream 来简单地读取以缓冲和写出,但后来我听说使用java.nio.FileChannel 可能会提高性能。

我没有资源来使用我拥有的数据运行一个严肃的、受控的测试,但似乎对于每种方法的优点没有达成共识(除了 FileChannel 是线程安全的)。一些用户报告 FileChannel 非常适合较小的文件,其他用户报告较大的文件速度会大大提高。

我想知道是否有人确切地知道创建FileChannel 的初衷是什么:它是为了更好的性能而设计的吗?在什么情况下?对于一般类型的数据是否有明确的性能提升,或者我应该期望看到的差异是微不足道的,因为我没有处理足够专业的数据?

编辑:假设我的数据不需要是线程安全的。

【问题讨论】:

  • 是的,类似的问题已经被问过很多次了,但是我很清楚那里的高级 IO 包。我现在更关心的是两者的原始性能比较。

标签: java performance file filestream filechannel


【解决方案1】:

FileChannel.transferFrom/To 应该比文件复制的 IO 流更快。

或者您可以简单地使用 Java 7 的 java.nio.file.Files.copy(source, target)。这应该尽可能快。

但是,最终性能不会有明显不同 - 硬盘速度是瓶颈。


FileChannel 不是非阻塞的,也不是可选的。不确定他们将来是否会添加这些功能。 Java 7 有AsynchronousFileChannel。

【讨论】:

  • 我想补充一点,根据实现,transferXXX() 操作可能会快很多,因为数据不会在内存中的内核和用户空间之间复制。
  • 它应该是,正如它声称的那样——如果这个 API 至少不比流 API 慢,那将是一种耻辱。然而遗憾的是,许多人报告说它在许多情况下确实比较慢。
【解决方案2】:

输入和输出流假定以流样式访问文件或资源。有一些额外的项目可以帮助(数组读取),但基本概念是一次读取一个或多个字符的流(可能会阻塞,直到有更多可用字符)。

通道是将信息复制到缓冲区的方法。这提供了对输入和输出例程的较低级别的访问。通过深思熟虑的缓冲区大小,速度提升可能令人印象深刻。围绕缓冲区构建代码可以减少读取循环所花费的时间(也可以提高性能)。最后,虽然可以对输入流状态进行预检查以避免阻塞,但 Channels 和 Buffers 允许操作以非阻塞方式执行(即使在最坏的条件下)。

【讨论】:

    【解决方案3】:

    你看过commons-io吗?

    FileUtils.copyFileToDirectory(srcFile, destDir);
    

    【讨论】:

    • 我并不真正需要那么多 IO 功能。这不是一个 IO 繁重的程序,只有一个操作偶尔会复制大量文件并且需要快速。
    • 这就是我提到它的原因。 IO 性能很大程度上取决于缓冲策略。该库可用多年,不断更新并花费大量编程时间。我认为它的性能比自己的实现要好,即使花费了一定的金额。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多