2010-04-13 2 views
6

Я могу «исправить» следующее исключение с помощью цикла try-catch, но я не могу понять причину.Java: что такое IOEXceptions в readLine() для BufferedReader?

  1. Почему деталь "in.readLine()" продолжает воспламенять IOExceptions?
  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); 
    } 
} 
} 
+2

Учебное пособие по исключению солнца: http://java.sun.com/docs/books/tutorial/essential/exceptions/index.html – BalusC

ответ

7

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

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

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

1

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

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

1

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

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

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

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

+2

@downvoter - позвольте мне исправить то, что вы считаете неправильным с этим ответом. – Bozho

2

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 { ... 
3
  1. Он не будет "непрерывно воспламенить" их, он просто может бросить их каждый раз, вы вызовете его. В вашем случае, если он что-то бросает, значит, что-то пошло не так с вашим стандартным вводом.
  2. Цель состоит в том, чтобы гарантировать, что вы, программист, использующий API, имеете дело с проблемой, поскольку в целом предполагается, что это восстанавливаемая проблема, хотя в вашем конкретном случае это будет смертельным для всей вашей программы.
0

Использование 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 blocks рекомендуется для безопасного программирования.

Смежные вопросы