7

全部,

我试图确保在捕获 IOException 时关闭使用 BufferedReader 打开的文件,但看起来好像我的 BufferedReader 对象超出了 catch 块的范围。

public static ArrayList readFiletoArrayList(String fileName, ArrayList fileArrayList)
{
    fileArrayList.removeAll(fileArrayList);

    try {
        //open the file for reading
        BufferedReader fileIn = new BufferedReader(new FileReader(fileName));

        // add line by line to array list, until end of file is reached
        // when buffered reader returns null (todo). 
        while(true){
                fileArrayList.add(fileIn.readLine());
            }
    }catch(IOException e){
        fileArrayList.removeAll(fileArrayList);
        fileIn.close(); 
        return fileArrayList; //returned empty. Dealt with in calling code. 
    }
}

Netbeans 抱怨它在 catch 块中“找不到符号 fileIn”,但我想确保在 IOException 的情况下 Reader 被关闭。如果没有第二个 try/catch 结构的丑陋,我怎么能做到这一点?

对于这种情况下的最佳实践的任何提示或指示,我们将不胜感激,

4

7 回答 7

24
 BufferedReader fileIn = null;
 try {
       fileIn = new BufferedReader(new FileReader(filename));
       //etc.
 } catch(IOException e) {
      fileArrayList.removeall(fileArrayList);
 } finally {
     try {
       if (fileIn != null) fileIn.close();
     } catch (IOException io) {
        //log exception here
     }
 }
 return fileArrayList;

关于上面代码的一些事情:

  • close 应该在 finally 中,否则当代码正常完成时,或者除了 IOException 之外还有其他异常时,它不会被关闭。
  • 通常,您有一个静态实用程序方法来关闭这样的资源,以便它检查 null 并捕获任何异常(除了在此上下文中登录之外,您永远不想做任何事情)。
  • return 属于 try 之后,因此主线代码和异常捕获都有一个没有冗余的 return 方法。
  • 如果你把 return 放在 finally 里面,它会产生一个编译器警告。
于 2010-04-15T22:09:24.223 回答
1

一旦你点击了 catch 块,在 try 中声明的任何变量都不再是作用域了。声明 BufferedReader fileIn = null; 在 try 块上方,然后将其分配到内部。在您的 catch 块中,执行 if(fileIn != null) fileIn.close();

于 2010-04-15T22:08:29.717 回答
1

它抱怨符号不存在,因为它不存在。它在 try 块中。如果要引用 fileIn,则需要在 try 之外声明它。

但是,听起来您确实想将关闭放在 finally 块中:无论成功还是失败,您都应该在返回之前关闭文件。

public static ArrayList readFiletoArrayList(String fileName, ArrayList fileArrayList)
{
    fileArrayList.removeAll(fileArrayList);

    BufferedReader fileIn = null;
    try {
        //open the file for reading
        fileIn = new BufferedReader(new FileReader(fileName));

        // add line by line to array list, until end of file is reached
        // when buffered reader returns null (todo). 
        while(true){
                fileArrayList.add(fileIn.readLine());
            }
    }catch(IOException e){
        fileArrayList.removeAll(fileArrayList); 
    }finally{
        if(fileIn != null) fileIn.close();
    }
    return fileArrayList;
}
于 2010-04-15T22:08:41.697 回答
1

我首选的在异常后执行清理的方法(当清理也可能引发异常时)是将代码放在另一个 try/finally 块中的 try 块中,如下所示:

public static ArrayList readFiletoArrayList(String fileName, ArrayList fileArrayList) {
    fileArrayList.removeAll(fileArrayList);

    try {
        //open the file for reading
        BufferedReader fileIn = null;

        try {
            fileIn = new BufferedReader(new FileReader(fileName));
            // add line by line to array list, until end of file is reached
            // when buffered reader returns null (todo). 
            while(true){
                fileArrayList.add(fileIn.readLine());
            }
        } finally {
            if (fileIn != null) {
                fileIn.close();
            }
        }
    }catch(IOException e){
        fileArrayList.removeAll(fileArrayList);
        return fileArrayList; //returned empty. Dealt with in calling code. 
    }
}
于 2010-04-15T22:16:42.023 回答
0

将声明移出 try 块:

public static ArrayList readFiletoArrayList(String fileName, ArrayList fileArrayList)
{
    fileArrayList.removeAll(fileArrayList);

    BufferedReader fileIn = null;
    try {
        //open the file for reading
        fileIn = new BufferedReader(new FileReader(fileName));

        // add line by line to array list, until end of file is reached
        // when buffered reader returns null (todo). 
        while(true){
                fileArrayList.add(fileIn.readLine());
            }
    }catch(IOException e){
        fileArrayList.removeAll(fileArrayList);
        fileIn.close(); 
        return fileArrayList; //returned empty. Dealt with in calling code. 
    }
}

但是,您仍然需要小心fileIn在尝试关闭它之前实际初始化的内容:

if (fileIn != null)
    fileIn.close();
于 2010-04-15T22:07:41.107 回答
0

在 try 块之外声明 BufferedReader 并将其设置为 null,然后如果它不为 null,则使用 finally 块将其关闭。fileArrayList 也是通过引用传递的,因此对其所做的任何更改都将发生在您传入的对象上,因此无需返回它。

    public static ArrayList readFiletoArrayList(String fileName, ArrayList fileArrayList)
{
    fileArrayList.removeAll(fileArrayList);
    BufferedReader fileIn = null;
    try {
        //open the file for reading
        fileIn = new BufferedReader(new FileReader(fileName));

        // add line by line to array list, until end of file is reached
        // when buffered reader returns null (todo). 
        while(true){
                fileArrayList.add(fileIn.readLine());
            }
    }catch(IOException e){
        fileArrayList.removeAll(fileArrayList);  
    }finally
    {
       try
       {
           if(fillIn != null)
               fileIn.close();
       }
       catch(IOException e){}
    }
    return fileArrayList; //returned empty. Dealt with in calling code.
}
于 2010-04-15T22:15:16.413 回答
0

最好不要处理null——Java中资源获取和释放的一般习惯用法是

final Resource resource = acquire();
try { use(resource); }
finally { resource.release(); }

所以:

public static List<String> readFiletoArrayList(String fileName,
        List<String> fileArrayList, String charsetName) {
    fileArrayList.clear(); // why fileArrayList.removeAll(fileArrayList) ?
    try {
        InputStream file = new FileInputStream(fileName);
        try {
            InputStreamReader reader = new InputStreamReader(file, charsetName);
            BufferedReader buffer = new BufferedReader(reader);
            for (String line = buffer.readLine(); line != null; line = buffer
                    .readLine()) {
                fileArrayList.add(line);
            }
        } finally {
            try {
                file.close();
            } catch (IOException e) {
                e.printStackTrace(); // you do not want this to hide an
                // exception thrown earlier so swallow it
            }
        }
    } catch (IOException e) {
        fileArrayList.clear(); // returned empty. Dealt with in client
    }
    return fileArrayList;
}

在这里查看我的观点

如果您使用的是阅读器,则必须像我在这里所做的那样指定编码。如果您想读取字节,请忘记阅读器。此外,如果您使用readLine(),您必须忘记行尾字符 - 如果这是一个问题,请考虑BufferedReader完全省略。

于 2013-07-18T21:21:58.747 回答