Как закрыть файл после перехвата IOException в Java? - PullRequest
7 голосов
/ 16 апреля 2010

All

Я пытаюсь убедиться, что файл, который я открыл с помощью BufferedReader, закрывается, когда я ловлю IOException, но кажется, что мой объект 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 жалуется, что «не может найти символ fileIn» в блоке catch, но я хочу убедиться, что в случае IOException, что Reader закроется. Как я могу сделать это без уродства второй конструкции try / catch вокруг первой?

Любые советы или указания относительно наилучшей практики в этой ситуации приветствуются,

Ответы [ 7 ]

23 голосов
/ 16 апреля 2010
 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 должно быть в конечном счете, иначе оно не закроется, когда код завершится нормально, или если будет сгенерировано какое-то другое исключениекроме IOException.
  • Как правило, у вас есть метод статической утилиты для закрытия ресурса, подобного этому, чтобы он проверял на нулевое значение и перехватывал любые исключения (которые вы никогда не захотите делать, кроме входа в систему в этом контексте).
  • Возврат принадлежит после попытки, так что и код основной строки, и перехват исключений имеют метод возврата без избыточности.
  • Если вы поместите возвращение внутри finally, он сгенерирует компиляторпредупреждение.
1 голос
/ 16 апреля 2010

Мой предпочтительный способ выполнить очистку после исключения (когда очистка может также вызвать исключение) - поместить код в блок try внутри другого блока try / finally, как показано ниже:

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. 
    }
}
1 голос
/ 16 апреля 2010

Он жалуется на то, что символа там нет, потому что его нет. Это в блоке try. Если вы хотите сослаться на fileIn, вам нужно объявить его вне попытки.

Однако на самом деле это звучит так, как будто вы хотите поместить закрытие в блок 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;
}
1 голос
/ 16 апреля 2010

После того, как вы нажмете блок catch, все переменные, объявленные в попытке, больше не будут ограничены. Объявить BufferedReader fileIn = null; над блоком try, затем назначьте его внутри. В вашем блоке catch выполните if (fileIn! = Null) fileIn.close ();

0 голосов
/ 19 июля 2013

Лучше не иметь дело с 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.

0 голосов
/ 16 апреля 2010

Объявите BufferedReader вне блока try и установите для него значение 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.
}
0 голосов
/ 16 апреля 2010

Переместить объявление из блока 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();
...