【问题标题】:Inputstream and Outputstream with reading a list of filesInputstream 和 Outputstream 读取文件列表
【发布时间】:2011-08-13 03:53:01
【问题描述】:

我有这个 ArrayList 文件

for(File file : files){

    InputStream in = FileInputStream(file);
    // process each file and save it to file
    OutputStream out = FileOutputStream(file);
    try{

    } finally {
       in.close();
       out.close();
    }
}

性能真的很慢,因为每个循环都有一个输入/输出 close(),有没有更好的方法来做到这一点?我试图将输出流置于循环之外,但它不起作用。

【问题讨论】:

  • hmm...但是当同时读取多个文件时它至少应该更快...在不同的线程上...如果您正在阅读很多文件..那么这应该是有道理的跨度>
  • (如果new FileOutputStream 抛出异常会发生什么情况(可能是FileNotFoundException,但也可能是未经检查的异常)?in.close(); 也是如此。您希望每个资源有一个 try-finally .)

标签: java inputstream fileoutputstream


【解决方案1】:

使用缓冲流会产生巨大的不同。

试试这个:

for(final File file : files) {

    final InputStream in = new BufferedInputStream(new FileInputStream(file));
    final OutputStream out = new BufferedOutputStream(new FileOutputStream(new File(...)));
    try {
        // Process each file and save it to file
    }
    finally {
        try {
            in.close();
        }
        catch (IOException ignored) {}
        try {
            out.close();
        }
        catch (IOException ignored) {}
    }
}

请注意,关闭流时可能抛出的IOExceptions 必须忽略,否则您将丢失潜在的初始异常。

另一个问题是两个流都在同一个文件上,这是行不通的。所以我想你正在使用两个不同的文件。

【讨论】:

  • 我正在尝试这个并就结果回复你
  • 我建议每个基础资源使用一个try-finally。如果new BufferedOutputStream(new FileOutputStream(new File(...))) 抛出异常,你就会一团糟。如果关闭输出流,比如说,抛出一个异常,你刚刚创建了一个损坏的文件并忽略了它。可能还有其他问题,但是如果您以不聪明的方式进行操作,那么一切都会正常进行,您无需考虑。
  • 刚试了一下,结果比以前的版本快两倍,而且不会占用任何空间。
【解决方案2】:

close() 最多可能需要 20 毫秒。我怀疑这是你的程序,除非你有 1000 个文件。

我怀疑您的性能问题是缺少缓冲输入和输出。你也可以展示你的缓冲包装器吗?

【讨论】:

  • 输出文件大约200MB,所以每次循环关闭200MB文件,会不会很慢?
  • close() 关闭 flush() 所以刷新到磁盘(最多)100Mb 会减慢它是的。
  • 如果你有一个正在读/写的磁盘,你应该期望它以大约每秒 30 MB 的速度读/写。如果您正在读取和写入 200 MB,则大约需要 13 秒。 200*2/30。这需要多长时间?
  • 它吃掉了我在 c:\ 中的所有 /temp,无论如何我认为缓冲区解决了问题
【解决方案3】:

您当然可以构建一个 OutputStreams 队列并将其卸载到处理这些输出流关闭的后台线程。输入流也一样。 或者,您可以将其留给 JVM 来执行 - 只需不要关闭文件,而是在对象完成时将其留给 GC 来执行。

【讨论】:

  • 所以你的意思是我不必 close() ?
  • 这不是关于“必须”——因为这完全取决于上下文。我个人不会将 close() 留给 jvm,但是你可以这样做。
  • 如果您尝试跨线程拆分,实际上可能会降低 I/O 的性能。特别是如果它碰巧运行那些旧的旋转介质机电设备。 (虽然你得到了缓冲,但想想那些可怜的小脑袋,就像他们失去了鸡一样。)
猜你喜欢
  • 2012-08-03
  • 2011-08-25
  • 2019-06-12
  • 2012-04-30
  • 1970-01-01
  • 2018-02-25
  • 1970-01-01
  • 1970-01-01
  • 2018-10-30
相关资源
最近更新 更多