Подтвердить что ты не робот

Каков правильный способ тихо закрыть InputStream в блоке finally без потери исходного исключения?

Мне интересно, будет ли нижеследующий код закрывать InputStream в окончательном блоке правильно

InputStream is = new FileInputStream("test");
try {
    for(;;) {
        int b = is.read();
        ...
    }
} finally {
    try {
        is.close();
    } catch(IOException e) {
    }
}

Если исключение происходит во время is.read(), будет ли оно игнорироваться/подавляться, если исключение происходит во время is.close()?

4b9b3361

Ответ 1

Исключение из is.close() будет подавлено, и исключение из is.read() будет тем, которое распространяется вверх.

Ответ 2

Лучший способ - использовать Java 7 и использовать try с ресурсами или сделать то же самое вручную и добавить исключение из закрытия как исключенное исключение.

Предварительная Java 7: Если вы выбрасываете свое собственное исключение, вы можете добавить в него исключение с нарушением, как это сделано в Java 7 (в вашем случае создайте поля List List, и вы получите исключения из операции закрытия и при работе с вашим исключением, посмотрите там тоже. Если вы не можете этого сделать, я не знаю ничего лучше, чем просто зарегистрировать его.

примеры: из Учебники Java

static String readFirstLineFromFile(String path) throws IOException {
    try (BufferedReader br = new BufferedReader(new FileReader(path))) {
        return br.readLine();
    }
}

но лучшая форма:

static String readFirstLineFromFile(String path) throws IOException {
    try (FileReader fr = new FileReader(path);
         BufferedReader br = new BufferedReader(fr)) {
        return br.readLine();
    }
}

Таким образом, даже если создание FileReader является успешным, но создание BufferedReader завершается с ошибкой (например, недостаточно памяти), FileReader будет закрыт.

Ответ 3

спецификации Java 6 говорят

Если выполнение блока try завершается внезапно по любой другой причине R, тогда выполняется блок finally. Тогда есть выбор: Если окончательный блок завершается нормально, то оператор try внезапно завершается по причине R. Если блок finally завершается внезапно для разума S, то оператор try внезапно завершается по причине S (и причина R отбрасывается).

Итак, вы правы, вы потеряете исходное исключение.

Решение, вероятно, состоит в том, чтобы написать ваш блок finally настолько защитно, что это большой сюрприз (стоит размножаться), если блок finally завершится неудачей, чем если исключение выйдет из блока catch try.

Итак, например, если возможно, что поток может быть пустым при попытке закрыть его, проверьте его:

InputStream is = new FileInputStream("test");
try {
    for(;;) {
        int b = is.read();
        ...
    }
} finally {
    try {
        if( is!=null ) {
            is.close();
        }
    } catch(IOException e) {
    }
}

В Java 7 решение Alpedar - это, конечно, путь.

Ответ 4

Вы можете закрыть его с помощью IOUtils https://commons.apache.org/proper/commons-io/

    public void readStream(InputStream ins) {

    try {
        //do some operation with stream         
    } catch (Exception ex) {
        ex.printStackTrace();           
    } finally {
        IOUtils.closeQuietly(ins);
    }       
}

Ответ 5

С кодом, который вы отправили:

  • Если is.close() выбрасывает IOException, он отбрасывается и распространяется исходное исключение.
  • Если is.close() выбрасывает что-то другое (a RuntimeException или Error), оно распространяется и исходное исключение отбрасывается.

С Java 7 правильный способ закрыть InputStream без потери исходного исключения состоит в использовании try-with-resources statement:

try (InputStream is = new FileInputStream("test")) {
    for(;;) {
        int b = is.read();
        // ...
    }
}

До появления Java 7 все, что вы делаете, просто отлично, за исключением того, что вы можете поймать все исключения вместо просто IOException s.

Ответ 6

Основываясь на вашем примере кода, если в точке int b = is.read(); возникает исключение, тогда исключение будет поднято выше цепочки вызовов.

Обратите внимание, что блок finally все равно будет выполняться, и если будет отклонено Inputstream другое исключение, но это исключение будет "проглочено", что может быть приемлемым в зависимости от вашего варианта использования.

Изменить:

Основываясь на названии вашего вопроса, я бы добавил, что то, что у вас есть, на мой взгляд. Вы можете дополнительно добавить блок catch, чтобы явно обрабатывать (или, возможно, обертывать) любое исключение в первом блоке try, но также допустимо, чтобы любые исключения IO поднимались - это действительно зависит от вашего API. Это может быть или не быть приемлемым, чтобы позволить исключениям IO поднимать. Если это так, то что у вас получилось - если это не так, тогда вы можете обработать/обернуть исключение IO с чем-то более подходящим для вашей программы.

Ответ 7

Как насчет следующего решения:

InputStream is = new FileInputStream("test");
Exception foundException=null;
try {
    for(;;) {
        int b = is.read();
        ...
    }
} catch (Exception e){
  foundException=e;
}
finally {
    if(is!=null)
    try {
        is.close();
    } catch(IOException e) {
    }
}
//handle foundException here if needed

Ответ 8

Если исключение происходит во время is.read(), будет ли оно игнорироваться/подавляться, если исключение происходит во время is.close()?

Да. У вас есть блок catch для исключения в close(), который не перебрасывает исключение. Ergo не размножается и не обновляется.

Ответ 9

Это образец, который поможет понять вашу проблему, если вы объявите сканер в блоке try-catch, он предоставит компилятору предупреждение о том, что ресурс не закрыт. поэтому либо сделайте это локально, либо просто в try()

import java.util.InputMismatchException;
import java.util.Scanner;

class ScanInt {
public static void main(String[] args) {
    System.out.println("Type an integer in the console: ");

    try (Scanner consoleScanner = new Scanner(System.in);) {
        System.out.println("You typed the integer value: "
                + consoleScanner.nextInt());

    } catch (InputMismatchException | ArrayIndexOutOfBoundsException exception) {
        System.out.println("Catch Bowled");
        exception.printStackTrace();

    }
    System.out.println("----------------");
}
}