Java: для чего нужны IOEXceptions в readLine () в BufferedReader? - PullRequest
6 голосов
/ 13 апреля 2010

Я могу "исправить" приведенное ниже исключение с помощью цикла try-catch, но не могу понять причину.

  1. Почему часть "in.readLine ()" непрерывно зажигает исключения IOException?
  2. Какова на самом деле цель бросать такие исключения, цель, вероятно, не просто побочные эффекты?

Код и IOExceptions

$ javac ReadLineTest.java 
ReadLineTest.java:9: unreported exception java.io.IOException; must be caught or declared to be thrown
  while((s=in.readLine())!=null){
                      ^
1 error
$ cat ReadLineTest.java 
import java.io.*;
import java.util.*;

public class ReadLineTest {
 public static void main(String[] args) {
  String s;
  BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
  // WHY IOException here?
  while((s=in.readLine())!=null){
   System.out.println(s);
  }
 }
}

Ответы [ 6 ]

7 голосов
/ 13 апреля 2010

Основная идея заключается в том, что BufferedReader делегирует другой тип Reader, поэтому он передает это исключение.

Этот другой тип Reader может считывать данные с какого-либо нестабильного внешнего ресурса, например, файловой системы в случае FileReader. Чтение файловой системы может завершиться неудачей по многим причинам в любое время. (Ситуация ухудшается, если Reader получает свои данные из сетевого потока). Файл может быть удален из-под вас (в зависимости от файловой системы и операционной системы).

Поскольку вы не можете предсказать, что произойдет с кодом, вы получите проверенное исключение - дело в том, что API говорит вам, что вам следует подумать о том, что эта операция может не сработать, даже если с вашим код.

3 голосов
/ 13 апреля 2010
  1. Он не будет "постоянно зажигать" их, он просто может выбрасывать их каждый раз, когда вы вызываете его. В вашем случае, если он выдает что-то, значит, что-то пошло не так с вашим стандартным вводом.
  2. Цель состоит в том, чтобы гарантировать, что вы, программист, использующий API, справитесь с проблемой, поскольку обычно предполагается, что она является восстанавливаемой проблемой - хотя в вашем конкретном случае это будет фатальным для всей вашей программы.
2 голосов
/ 13 апреля 2010

BufferedReader.readLine() объявлено как потенциально вызывающее исключение, см: http://java.sun.com/j2se/1.3/docs/api/java/io/BufferedReader.html#readLine()

Вам нужно либо перехватить его, либо объявить свой основной метод как выбрасывающий IOException.

То есть, либо сделайте это:

try {
    while((s=in.readLine()) != null){
        System.out.println(s);
     }
} catch(IOException e) {
    // Code to handle the exception.
}

Или

public static void main(String[] args) throws IOException { ...
1 голос
/ 09 ноября 2017

Использование Scanner для чтения файлов (или другого типа ввода) может быть крайне неэффективным в средних / крупных ситуациях. Если у вас есть проблемы с производительностью при чтении тысяч или миллионов строк, я настоятельно рекомендую вместо этого использовать класс BufferedReader . Пример использования BufferedReader для чтения строк из System.in показан ниже:

public static void main(String[] args) throws Exception {

    String line = null;
    BufferedReader br = new BufferedReader (new InputStreamReader(System.in));

    try {
        /* This is protected code. If an problem occurs here, catch block is triggered */
        while ( (line = br.readLine()) != null ){
            System.out.println(line); 
        }
    }
    catch (IOException e){
        throw new IOException("Problem reading a line",e);
    }
}

IOException следует использовать в блоке try/catch, поэтому его можно запускать всякий раз, когда защищенный код внутри try страдает от "исключительного" поведения, такого как ошибка. У Java есть свои исключения, которые вызываются при возникновении подобной ситуации. Например, ArrayIndexOutOfBoundsException выбрасывается, когда вы определяете массив a размера n и пытаетесь получить доступ к позиции a[n+1] где-нибудь в вашем коде. Как и ArrayIndexOutOfBoundsException, существует множество других классов исключений, которые вы можете создавать и настраивать с помощью собственных сообщений. Подходящий для исключения код должен находиться в защищенной зоне в блоке try. Когда в этом блоке возникает исключение, оно будет обработано вместе с ним в блоке catch.

Смотри, что тебе не нужно строить if/else операторы, чтобы предвидеть ситуацию с ошибкой и выдавать исключение для каждого случая. Вам просто нужно связать возможные исключительные ситуации между try и catch блоком. Подробнее о блоки try / catch рекомендуется для безопасного программирования.

1 голос
/ 13 апреля 2010

Выдается, если с вводом / выводом возникает исключительная ситуация, например, источник потока больше не доступен.

В таких случаях ваша программа должна быть в состоянии восстановить. Либо перечитав источник, либо используя некоторые значения по умолчанию, либо предупредив пользователя о проблеме.

Вы вынуждены catch сделать это, потому что это проверенное исключение, и вы должны быть в состоянии восстановиться после него.

Конечно, у вас есть возможность объявить, что текущий метод throws это исключение для методов вызывающих, но вам придется в конце концов его перехватить (или позволить ему всплыть до основного метода, когда он просто печатается на консоль и выполнение программы прекращаются)

1 голос
/ 13 апреля 2010

IOException является проверенным исключением . Вы должны либо перехватить его, либо передать его вызывающему методу. Проверенные исключения вызваны внешними действующими лицами, такими как отсутствующий файл, неисправный диск или все, что вы не можете восстановить в программном коде.

Однако исключение Unchecked, такое как ArrayIndexOutofBoundsException, вызвано неверной логикой в ​​программе. Вы можете уничтожить его, используя условие if вне вашего дефектного кода (что-то вроде if currIndex> array.length). В случае проверенного исключения такое положение отсутствует

...