Java,异常处理和关闭流与try,最后

时间:2012-04-01 22:37:24

标签: java stream

我只是想知道是否有更好的方法来处理这个问题。我对流的理解是,只要你关闭一个流,封装在其中的任何流都将被关闭,这就是我最终只关闭TarArchiveOutputStream的原因。如果我在rawDir或archiveDir上获取FileNotFound,我想记录它,否则我想抛出任何其他内容。

public static void createTarGzOfDirectory(File rawDir, File archiveFile) throws IOException {
    FileOutputStream fOut = null;
    BufferedOutputStream bOut = null;
    GzipCompressorOutputStream gzOut = null;
    TarArchiveOutputStream tOut = null;
    try {
        fOut = new FileOutputStream(archiveFile);
        bOut = new BufferedOutputStream(fOut);
        gzOut = new GzipCompressorOutputStream(bOut);
        tOut = new TarArchiveOutputStream(gzOut);
        addFileToTarGz(tOut, rawDir, "");
    } catch (FileNotFoundException e) {
        log.error("File not found: " + e);
    } finally {
        if(tOut != null) {
            tOut.finish();
            tOut.close();
        }
    }

关于改进事物的任何其他考虑或想法?

3 个答案:

答案 0 :(得分:3)

  

我对流的理解是,只要你关闭一个流,封装在其中的任何流都将被关闭......

这是正确的。

但是,您的代码(有效地)假设如果tOutnull,则链中没有其他流已创建。这是一个有点狡猾的假设。考虑这个顺序:

  1. FileOutputStream已创建并已分配到fOut
  2. BufferedOutputStream已创建并已分配到bOut
  3. GzipCompressorOutputStream构造函数抛出异常或错误。 (也许堆已经满了......)。
  4. catch被跳过...错误的例外。
  5. finally检查tOut,发现它是null,并且什么也没做。
  6. 净结果:我们泄露了FileOUtputStream所持有的文件描述符/频道。

    获得此示例(绝对)正确的关键是了解哪些流对象拥有关键资源,并确保关闭此流。其他不保存资源的流不必关闭。

    } finally {
        if (fOut != null) {
            fOut.close();
        }
    }
    

    另一点是,您需要在tOut.finish()电话后将try电话移至addFileToTarGz阻止。

    • 如果addFileToTarGz来电引发异常,或者你没有那么远,那么finish来电就是浪费时间。

    • finish调用将尝试将索引写入存档,并且可能会抛出IOException。如果在finally块中发生这种情况,则finally块中用于关闭流链的任何后续代码将不会被执行...并且文件描述符将被泄露。

答案 1 :(得分:1)

虽然它看起来很丑陋,而且可能不太可能出现这种情况,但你应该将它们全部关闭。是的,如果你关闭TarArchiveOutputStream,它应该关闭underlyning流。但是,根据实施情况,情况可能并非总是如此。而且,可能主要是,如果其中一个中间构造函数抛出异常,则tOut将为null,但其他可能不是。这意味着您的流已打开,但您没有关闭任何流。

答案 2 :(得分:0)

您可以将所有构造函数链接在一起:

    tOut = new TarArchiveOutputStream(new GzipCompressorOutputStream(new BufferedOutputStream(new FileOutputStream(archiveFile))));

并为自己保存6行初始化和3个局部变量以进行调试。不是每个人都喜欢用这种方式链接东西 - 我个人觉得它更具可读性,但你团队的其他成员可能更喜欢它。

关于关闭流,看起来对我来说是正确的。