我需要关闭PrintStream包装的FileOutputStream吗?

28

我正在使用FileOutputStreamPrintStream,就像这样:

class PrintStreamDemo {  
    public static void main(String args[]) { 
        FileOutputStream out; 
        PrintStream ps; // declare a print stream object
        try {
            // Create a new file output stream
            out = new FileOutputStream("myfile.txt");

            // Connect print stream to the output stream
            ps = new PrintStream(out);

            ps.println ("This data is written to a file:");
            System.err.println ("Write successfully");
            ps.close();
        }
        catch (Exception e) {
            System.err.println ("Error in writing to file");
        }
    }
}

我只关闭了PrintStream,是否还需要关闭FileOutputStream (out.close();)呢?


请查看源代码:http://www.docjar.com/html/api/java/io/PrintStream.java.html - jtoberon
顺便说一下,PrintStream 的美妙之处在于你可以只使用字符串(用作文件名)或 File 对象。你不需要打开一个 FOStream 就可以使用它在 PrintStream 中。 - Mechkov
5个回答

33
不,您只需要关闭最外层的流。它将一直委托到包装的流。
但是,您的代码存在一个概念上的错误,关闭应该在finally中进行,否则当代码在打开和关闭之间抛出异常时,它将永远不会被关闭。
例如:
public static void main(String args[]) throws IOException { 
    PrintStream ps = null;

    try {
        ps = new PrintStream(new FileOutputStream("myfile.txt"));
        ps.println("This data is written to a file:");
        System.out.println("Write successfully");
    } catch (IOException e) {
        System.err.println("Error in writing to file");
        throw e;
    } finally {
        if (ps != null) ps.close();
    }
}
< p >(请注意,我更改了代码以使用throw抛出异常,这样您就可以理解问题的原因,异常包含有关问题原因的详细信息)

或者,如果您已经在使用Java 7,则还可以利用ARM(自动资源管理;也称为try-with-resources),这样您就不需要手动关闭任何内容:

public static void main(String args[]) throws IOException { 
    try (PrintStream ps = new PrintStream(new FileOutputStream("myfile.txt"))) {
        ps.println("This data is written to a file:");
        System.out.println("Write successfully");
    } catch (IOException e) {
        System.err.println("Error in writing to file");
        throw e;
    }
}

当我添加finally块并尝试在其中执行ps.close()时,我会收到错误提示:variable ps might not have been initialized - hs2d
你需要用 null 进行初始化。 - BalusC
请注意,我更新了答案,并提供了一个更简洁的Java 7示例。 - BalusC

8
不,这里是PrintStreamclose()方法的实现:
public void close() {
    synchronized (this) {
        if (! closing) {
        closing = true;
        try {
            textOut.close();
            out.close();
        }
        catch (IOException x) {
            trouble = true;
        }
        textOut = null;
        charOut = null;
        out = null;
        }
    }

你可以看到 out.close(); 这一行代码关闭了输出流。

6
根据Javadoc显示,close方法会为您关闭底层流。

6

-2
不需要关闭其他组件。当您关闭流时,它会自动关闭其他相关组件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接