在java中捕获IOException后如何关闭文件?

在java中捕获IOException后如何关闭文件?,java,exception-handling,try-catch,ioexception,bufferedreader,Java,Exception Handling,Try Catch,Ioexception,Bufferedreader,全部, 我试图确保在捕获IOException时,已使用BufferedReader打开的文件处于关闭状态,但在捕获块中,我的BufferedReader对象似乎超出范围 public static ArrayList readFiletoArrayList(String fileName, ArrayList fileArrayList) { fileArrayList.removeAll(fileArrayList); try { //open the fi

全部,

我试图确保在捕获IOException时,已使用BufferedReader打开的文件处于关闭状态,但在捕获块中,我的BufferedReader对象似乎超出范围

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块中“找不到symbol fileIn”,但我想确保在发生IOException的情况下,读卡器被关闭。如果没有围绕第一个try/catch构造的第二个try/catch,我怎么能做到这一点呢


任何关于在这种情况下最佳实践的提示或建议都将不胜感激,

将声明移出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();

一旦到达catch块,try中声明的任何变量都不再具有作用域。声明BufferedReader fileIn=null;在try块上方,然后在内部指定它。在catch块中,执行if(fileIn!=null)fileIn.close()

它抱怨符号不存在,因为它不存在。在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;
}
关于上述代码的一些内容:

  • close应该在finally中,否则当代码正常完成时,或者如果在IOException之外引发了其他异常,它就不会被关闭
  • 通常,您有一个静态实用程序方法来关闭这样的资源,以便它检查null并捕获任何异常(在这个上下文中,除了日志之外,您永远不想对其执行任何操作)
  • 返回属于try之后,因此主线代码和异常捕获都有一个没有冗余的返回方法
  • 如果将返回放在finally中,它将生成编译器警告

在try块外部声明BufferedReader并将其设置为null,然后使用finally块关闭它(如果它不是null)。 此外,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.
}

我在异常后执行清理的首选方法(当清理可能也会引发异常时)是将代码放入另一个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. 
    }
}

最好不要处理
null
-:

因此:

公共静态列表readFiletoArrayList(字符串文件名,
列表fileArrayList,字符串charsetName){
fileArrayList.clear();//为什么选择fileArrayList.removeAll(fileArrayList)?
试一试{
InputStream文件=新文件InputStream(文件名);
试一试{
InputStreamReader=新的InputStreamReader(文件,charsetName);
BufferedReader buffer=新的BufferedReader(读卡器);
对于(字符串line=buffer.readLine();line!=null;line=buffer
.readLine()){
添加(行);
}
}最后{
试一试{
file.close();
}捕获(IOE异常){
e、 printStackTrace();//您不希望它隐藏
//先前抛出异常,因此请将其吞下
}
}
}捕获(IOE异常){
fileArrayList.clear();//返回空。在客户端处理
}
返回fileArrayList;
}
明白我的意思吗


如果您使用的是读卡器,您必须像我在这里所做的那样指定编码。如果要读取字节,请忘记读卡器。此外,如果使用<代码> ReadRead()/Cyt>您必须忘记行尾字符——如果这是一个问题,请考虑省略<代码> BufferedReader < /代码>。< /P>如果读者构造函数中有一个异常(例如,没有找到文件),那将被一个<代码> Null PoExtExeals< /Coad>炸毁。必须检查
catch
中的
null
。在catch中,您有
fileIn.close()也会引发IOException。编译器将不允许它。
最后为+1
。令人惊讶的是,很多答案都没有提到这一点。下面是一些Sun链接:您可以删除对
null
的检查并捕获
异常
,除非您计划告诉用户您无法关闭文件,而不是无法打开文件。但是,一般来说,用户并不关心。您关闭了BufferedRead,但没有关闭FileReader?关闭BufferedReader将自动关闭FileReader。@Bert:事实上,Java IO类遵循decorator模式。因此,在每个
close()
下,都会向上委托给修饰过的实例。在我看来,如果文件是为写入而不是读取而打开的,那么安全操作将要求关闭文件时发生的任何IOException都不会被吞没,除非已经有IOException渗透到调用堆栈中。吞下文件关闭操作引发的
IOException
可能是合理的,该操作本身在
Catch(IOException e)
中,但如果通过正常代码执行最终到达
,关闭时吞下
IOException
可能会导致调用者错误地认为某个文件是编写的,而实际上不是编写的。@supercat:你是对的,但这是文件读取。如果有装饰器,书写必须刷新装饰器(而不是依赖于关闭)。我经历了一些特殊情况——不公正地关闭了令人窒息的清理异常模式,但通常不考虑清理需要什么。在某些情况下,这没关系,但作为一种习惯,这似乎很危险。至于你的关联(封闭)问题,我建议你从少一点“背景故事”开始。你真正想知道的是(从我所知道的)如何处理从构造函数抛出的异常
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. 
    }
}
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;
}