关闭已在if语句中初始化的PrintWriter对象

时间:2015-08-11 13:00:07

标签: java

这可能是一个非常基本的问题,但我正在尝试创建一个执行进程的Java方法,并读取从该进程创建的输入流并写入新文件。我正在使用Runtime.getRuntime()。exec(cmd []),我想为特定的索引使用不同的参数,例如cmd [3] =“某事物”或cmd [3] =“其他东西”。我使用for循环来执行此操作,但对于cmd [3]的参数数组中的第一个索引,我希望它使用PrintWriter打印到新文件,因此我在顶部初始化后在if语句中初始化它for循环。如果我只是显示代码,那么你可能会更容易:

public static synchronized void myMethod(String [] argument3, File file) throws IOException{

    String[] cmd = {"command", "argument 1", "argument 2"};
    PrintWriter fileWriter = null;
    Scanner fileScanner = null;
    int i;
    for(i = 0; i < argument3.length; i++){
        fileWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file,true)));;
        cmd[3] = argument3[i];
        if(i == 0){
            fileWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file,false)));
        }
        Process p = Runtime.getRuntime().exec(cmd);
        fileScanner = new Scanner(p.getInputStream());

        while(fileScanner.hasNextLine()){
            fileWriter.println(fileScanner.nextLine());
        }
        fileWriter.close();
        fileScanner.close();

    }

}

所有这一切都运行正常,但在eclipse中我得到一个警告说我有资源泄漏我在if语句中初始化我的PrintWriter所以我只是好奇为什么那是因为我关闭它们在底部for循环?我知道它并没有太大的区别,因为无论如何我只是想尝试正确地清理我的代码。 提前致谢

4 个答案:

答案 0 :(得分:-1)

需要注意的重要事项是

throws IOException

这可以抛出,如果抛出,您的资源将不会被关闭。您应确保在任何情况下都关闭资源,即使抛出异常也是如此。使用...

try { ... } finally {   ... close here... } 

......为此。想象一下,当您的文件被读取时,会发生一些不好的事情。抛出IOException并且永远不会调用close()语句,这将是eclipse提到的可怕的资源泄漏

答案 1 :(得分:-1)

  

我收到一条警告,说我有资源泄漏,我在if语句中初始化了我的PrintWriter。

问题在于:

fileWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file,true)));
if (i == 0) {
    fileWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file,false)));
}
fileWriter.close();

第一次循环,当该条件成立时,你创建了两个PrintWriters,只有第二个被关闭。你只是放弃了第一个。相反,你可以像这样初始化它:

fileWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file, i != 0)));

但这提出了一个问题,为什么每次循环都会重新创建PrintWriter?只需在循环外创建一次。

另一个问题是,如果抛出异常,则不会实际执行任何清理代码。你需要的是一个try-catch-finally块,你可以保证你的清理代码被执行。如果您至少使用Java 7,则可以使用try-with-resources,它会自动为您完成所有清理工作:

void myMethod(String [] argument3, File file) throws IOException {
    String[] cmd = {"command", "argument 1", "argument 2"};
    try (PrintWriter fileWriter = new PrintWriter (file)) {
        for (int i = 0; i < argument3.length; i++) {
            Process process = Runtime.getRuntime().exec(cmd);
            try (Scanner fileScanner = new Scanner(process.getInputStream())) {
                cmd[3] = argument3[i];
                while (fileScanner.hasNextLine()) {
                    fileWriter.println(fileScanner.nextLine());
                }
            }
        }
    }
}

答案 2 :(得分:-1)

基本上,VM正在抱怨,因为两个内部对象永远不会关闭。

 for(i = 0; i < argument3.length; i++){
        fileWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file,true)));;
        cmd[3] = argument3[i];
        if(i == 0){
            fileWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file,false)));
        }
        Process p = Runtime.getRuntime().exec(cmd);
        fileScanner = new Scanner(p.getInputStream());

        while(fileScanner.hasNextLine()){
            fileWriter.println(fileScanner.nextLine());
        }
        fileWriter.close();
        fileScanner.close();

    }

你应该基本上将元素定义分开:

for (i = 0; i < argument3.length; i++) {
FileOutputStream fos;    
    if (i == 0)
        fos = new FileOutputStream(file, false);
    else
        fos = new FileOutputStream(file, true);
    OutputStreamWriter osw = new OutputStreamWriter(osw);
    fileWriter = new PrintWriter(osw);
    // do the rest
    // and then...
    fileWriter.close();
    fileScanner.close();
    osw.close();
    fos.close();
}

这将删除警告。

P.S。:正如之前的回答所示,将.close方法移动到finally块会被认为是最好的。

答案 3 :(得分:-1)

使用try catch finally阻止并关闭finally块中的ScannerPrintWriter,因为最终总是执行:

public static synchronized void myMethod(String[] argument3, File file) {
        String[] cmd = { "command", "argument 1", "argument 2" };
        PrintWriter fileWriter = null;
        Scanner fileScanner = null;
        try {
            for (int i = 0; i < argument3.length; i++) {
                fileWriter = new PrintWriter(new OutputStreamWriter(
                        new FileOutputStream(file, true)));
                cmd[3] = argument3[i];
                if (i == 0) {
                    fileWriter = new PrintWriter(new OutputStreamWriter(
                            new FileOutputStream(file, false)));
                }
                Process p = Runtime.getRuntime().exec(cmd);
                fileScanner = new Scanner(p.getInputStream());

                while (fileScanner.hasNextLine()) {
                    fileWriter.println(fileScanner.nextLine());
                }

            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            fileWriter.close();
            fileScanner.close();
        }
    }