2010-04-13 34 views
6

Tôi có thể "sửa" ngoại lệ dưới đây với vòng lặp cố gắng nhưng tôi không hiểu lý do.Java: IOEXceptions trong BufferedReader của readLine() cho là gì?

  1. Tại sao phần "in.readLine()" liên tục kích hoạt IOExceptions?
  2. Điều gì thực sự là mục đích của việc ném ngoại lệ như vậy, mục tiêu có lẽ không chỉ là nhiều tác dụng phụ?

Mã và 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

Hướng dẫn ngoại lệ về mặt trời: http://java.sun.com/docs/books/tutorial/essential/exceptions/index.html – BalusC

Trả lời

7

Ý tưởng cơ bản là một BufferedReader ủy quyền cho một loại Reader khác, do đó, nó đang vượt qua ngoại lệ đó.

Đó loại khác nhau của Reader có thể đọc từ một số loại tài nguyên bên ngoài không ổn định, nói một hệ thống tập tin trong trường hợp FileReader. Một hệ thống tập tin đọc có thể thất bại vì nhiều lý do bất cứ lúc nào. (Tình hình tồi tệ hơn nếu Reader đang lấy dữ liệu cơ bản của nó từ một luồng mạng). Tệp có thể bị xóa khỏi bên dưới bạn (tùy thuộc vào hệ thống tệp và hệ điều hành có liên quan).

Vì bạn không thể dự đoán điều gì sẽ xảy ra với mã, bạn nhận được ngoại lệ được kiểm tra - điểm là API cho bạn biết rằng bạn nên suy nghĩ về thực tế là thao tác này có thể không hoạt động ngay cả khi không có gì sai ma cua ban.

1

IOException là một checked exception. Bạn phải nắm bắt hoặc ném nó vào phương thức gọi điện của bạn. Các trường hợp ngoại lệ được kiểm tra là do các tác nhân bên ngoài gây ra, chẳng hạn như tệp bị thiếu, đĩa bị lỗi hoặc bất kỳ thứ gì mà bạn không thể khôi phục từ mã chương trình của mình.

Tuy nhiên, ngoại lệ không được kiểm soát như ArrayIndexOutofBoundsException là do logic bị lỗi trong chương trình. Bạn có thể phá hoại nó bằng cách sử dụng một điều kiện if bên ngoài mã lỗi của bạn (một cái gì đó giống như nếu currIndex> array.length). Không có quy định nào như vậy trong trường hợp ngoại lệ được kiểm tra

1

Nó được ném nếu xảy ra trường hợp ngoại lệ với I/O, ví dụ như nguồn của luồng không còn khả dụng nữa.

Trong những trường hợp như vậy, chương trình của bạn sẽ có thể khôi phục. Hoặc bằng cách đọc lại nguồn hoặc bằng cách sử dụng một số giá trị mặc định hoặc bằng cách cảnh báo cho người dùng về sự cố.

Bạn bị buộc phải catch nó, vì đó là ngoại lệ được kiểm tra và bạn có nghĩa vụ có thể khôi phục từ những trường hợp đó.

Tất nhiên, bạn có tùy chọn để tuyên bố rằng phương pháp hiện tại throws ngoại lệ này cho phương thức người gọi, nhưng bạn sẽ phải nắm bắt nó cuối cùng (hoặc để nó bong bóng lên phương pháp chính, khi nó đơn giản được in trên giao diện điều khiển và thực hiện chương trình dừng)

+2

@downvoter - hãy để tôi khắc phục những gì bạn nghĩ là sai với câu trả lời này. – Bozho

2

BufferedReader.readLine() bị tuyên bố là có khả năng ném một ngoại lệ, xem: http://java.sun.com/j2se/1.3/docs/api/java/io/BufferedReader.html#readLine()

bạn có thể cần phải nắm bắt nó, hoặc tuyên bố phương pháp chính của bạn như ném IOException.

Ie, hoặc làm điều này:

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

Hoặc

public static void main(String[] args) throws IOException { ... 
3
  1. Nó sẽ không "liên tục đốt cháy" cho họ, nó chỉ có thể ném chúng mỗi lần bạn gọi nó. Trong trường hợp của bạn, nếu nó ném một cái gì đó nó có nghĩa là một cái gì đó đã đi sai với đầu vào tiêu chuẩn của bạn.
  2. Mục đích là để đảm bảo rằng bạn, lập trình viên sử dụng API, giải quyết vấn đề, vì nói chung được giả định là một vấn đề có thể phục hồi - mặc dù trong trường hợp cụ thể của bạn, nó sẽ gây tử vong cho toàn bộ chương trình của bạn.
0

Sử dụng Scanner cho việc đọc file (hoặc loại khác của đầu vào) có thể cực kỳ hiệu quả vào giữa/tình huống quy mô lớn. Nếu bạn có mối quan tâm về hiệu suất đọc hàng nghìn hoặc hàng triệu dòng, tôi khuyên bạn nên sử dụng lớp BufferedReader để thay thế. Một ví dụ về cách sử dụng của BufferedReader để đọc các dòng từ System.in được hiển thị dưới đây:

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 nên được sử dụng trong try/catch khối do đó có thể được kích hoạt bất cứ khi nào mã bảo vệ bên try đau khổ của một hành vi "đặc biệt" như một lỗi . Java có ngoại lệ riêng của mình được đẩy lên khi tình huống tương tự xảy ra. Ví dụ: ArrayIndexOutOfBoundsException được trao quyền khi bạn xác định mảng a kích thước n và bạn cố gắng truy cập vào vị trí a[n+1] ở đâu đó trong mã của bạn. Là ArrayIndexOutOfBoundsException, có nhiều lớp Ngoại lệ khác mà bạn có thể ném và tùy chỉnh bằng các tin nhắn của riêng bạn. Mã phù hợp với ngoại lệ phải được đặt trong khu vực được bảo vệ trong khối thử. Khi ngoại lệ xảy ra trong khối đó, ngoại lệ sẽ được xử lý trong khối catch với nó.

Hãy xem bạn không cần phải xây dựng các tuyên bố if/else để dự đoán tình huống lỗi và ném Ngoại lệ cho từng trường hợp. Bạn chỉ cần liên kết các tình huống ngoại lệ có thể có giữa các khối trycatch. Xem thêm về try/catch blocks được khuyến khích để lập trình an toàn.

Các vấn đề liên quan