2013-08-26 89 views
11

Tôi là lập trình viên java mới bắt đầu theo số java tutorials.EOFException - cách xử lý?

Tôi đang sử dụng Chương trình Java đơn giản từ Java tutorials 's Data Streams Page và khi chạy, nó vẫn hiển thị EOFException. Tôi đã tự hỏi nếu điều này là bình thường, khi người đọc phải đến cuối tập tin cuối cùng.

import java.io.*; 

public class DataStreams { 
    static final String dataFile = "F://Java//DataStreams//invoicedata.txt"; 

    static final double[] prices = { 19.99, 9.99, 15.99, 3.99, 4.99 }; 
    static final int[] units = { 12, 8, 13, 29, 50 }; 
    static final String[] descs = { 
     "Java T-shirt", 
     "Java Mug", 
     "Duke Juggling Dolls", 
     "Java Pin", 
     "Java Key Chain" 
    }; 
    public static void main(String args[]) { 
     try { 
      DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(dataFile))); 

      for (int i = 0; i < prices.length; i ++) { 
       out.writeDouble(prices[i]); 
       out.writeInt(units[i]); 
       out.writeUTF(descs[i]); 
      } 

      out.close(); 

     } catch(IOException e){ 
      e.printStackTrace(); // used to be System.err.println(); 
     } 

     double price; 
     int unit; 
     String desc; 
     double total = 0.0; 

     try { 
      DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(dataFile))); 

      while (true) { 
       price = in.readDouble(); 
       unit = in.readInt(); 
       desc = in.readUTF(); 
       System.out.format("You ordered %d" + " units of %s at $%.2f%n", 
       unit, desc, price); 
       total += unit * price; 
      } 
     } catch(IOException e) { 
      e.printStackTrace(); 
     } 

     System.out.format("Your total is %f.%n" , total); 
    } 
} 

Nó biên dịch tốt, nhưng đầu ra là:

ý rằng DataStreams phát hiện một điều kiện end-of-file:

You ordered 12 units of Java T-shirt at $19.99 
You ordered 8 units of Java Mug at $9.99 
You ordered 13 units of Duke Juggling Dolls at $15.99 
You ordered 29 units of Java Pin at $3.99 
You ordered 50 units of Java Key Chain at $4.99 
java.io.EOFException 
     at java.io.DataInputStream.readFully(Unknown Source) 
     at java.io.DataInputStream.readLong(Unknown Source) 
     at java.io.DataInputStream.readDouble(Unknown Source) 
     at DataStreams.main(DataStreams.java:39) 
Your total is 892.880000. 

Từ 's Data Streams Page, nó nói Java tutorials bằng cách đánh bắt EOFException, thay vì thử nghiệm cho một giá trị trả lại không hợp lệ. Tất cả các triển khai của các phương thức DataInput đều sử dụng EOFException thay cho các giá trị trả về.

Vì vậy, điều này có nghĩa là bắt EOFException là bình thường, vì vậy chỉ cần nắm bắt và không xử lý nó là tốt, có nghĩa là kết thúc tệp là gì?

Nếu nó có nghĩa là tôi nên xử lý nó, xin vui lòng tư vấn cho tôi về cách làm điều đó.

EDIT

Từ những gợi ý, tôi đã cố định nó bằng cách sử dụng in.available() > 0 cho tình trạng while vòng lặp.

Hoặc, tôi không thể làm gì để xử lý ngoại lệ, bởi vì nó ổn.

+0

Loại bỏ các 'e.printStackT race(); 'trong khối' catch' sẽ loại bỏ bản in của dấu vết stack của exception. Thay vào đó để in nó, bạn nên có thể đăng nhập nó. – araknoid

Trả lời

14

Trong khi đọc từ tệp, bạn sẽ không chấm dứt vòng lặp của mình. Vì vậy, nó đọc tất cả các giá trị và đúng ném EOFException trên phiên bản kế tiếp của đọc tại dòng dưới đây:

price = in.readDouble(); 

Nếu bạn đọc tài liệu, nó nói:

Ném:

EOFException - nếu luồng đầu vào này kết thúc trước khi đọc tám byte.

IOException - luồng đã bị đóng và luồng đầu vào chứa không hỗ trợ đọc sau khi đóng, hoặc xảy ra lỗi I/O khác.

Đặt điều kiện chấm dứt thích hợp trong vòng lặp while để giải quyết vấn đề, ví dụ: bên dưới:

 while(in.available() > 0) <--- if there are still bytes to read 
+0

Tôi vừa thử nó, và nó hoạt động! thanks –

+1

Vòng lặp này sẽ thoát khi không có thêm dữ liệu * hiện có sẵn để đọc, * và * không * ở cuối luồng. 'InputStream.available()' không phải là một thử nghiệm cho kết thúc của luồng. Xem Javadoc. – EJP

1

Bạn có thể sử dụng while(in.available() != 0) thay vì while(true).

+1

hasNextLine() không phải là một phần của DataInputStream. Câu trả lời này là sai. – redFIVE

+0

Xin lỗi! Tôi không thấy điều đó. Tôi đã thay đổi nó ngay bây giờ. – akaHuman

+0

Câu trả lời này vẫn sai. 'InputStream.available()' không phải là một thử nghiệm cho kết thúc của luồng. Xem Javadoc. – EJP

2

Cách tốt nhất để xử lý việc này là chấm dứt vòng lặp vô hạn của bạn với điều kiện thích hợp.

Nhưng vì bạn đã yêu cầu xử lý ngoại lệ:

Hãy thử sử dụng hai lần đánh bắt. EOFException của bạn được mong đợi, do đó, có vẻ như không có vấn đề khi nó xảy ra. Bất kỳ ngoại lệ nào khác đều phải được xử lý.

... 
} catch (EOFException e) { 
    // ... this is fine 
} catch(IOException e) { 
    // handle exception which is not expected 
    e.printStackTrace(); 
} 
+0

đó là những gì họ đã làm trong ví dụ [Data Streams] (http://docs.oracle.com/javase/tutorial/essential/io/datastreams.html). nó cũng hoạt động. –

0

Bạn bắt IOException cũng bắt được EOFException, vì nó được kế thừa. Nếu bạn nhìn vào ví dụ từ tutorial, họ nhấn mạnh rằng bạn nên bắt EOFException - và đây là những gì họ làm. Để giải quyết vấn đề bạn bắt EOFException trước IOException:

try 
{ 
    //... 
} 
catch(EOFException e) { 
    //eof - no error in this case 
} 
catch(IOException e) { 
    //something went wrong 
    e.printStackTrace(); 
} 

Bên cạnh đó tôi không thích dữ liệu điều khiển lưu lượng sử dụng ngoại lệ - nó không phải là mục đích sử dụng các ngoại lệ và do đó (theo ý kiến ​​của tôi) phong cách thực sự xấu.

+0

cảm ơn ý kiến ​​của bạn về điều này. –

+0

Đó là * chính xác * mục đích sử dụng 'cho ngoại lệ của mình. Vấn đề với 'nguyên tắc' của bạn là ngoại lệ * là 'một dạng kiểm soát dòng chảy. – EJP

1

Ngoài ra, bạn có thể viết ra các số nguyên tố đầu tiên (như là một tiêu đề) sử dụng:

out.writeInt(prices.length); 

Khi bạn đọc các tập tin, trước tiên bạn đọc tiêu đề (đếm phần tử):

int elementCount = in.readInt(); 

for (int i = 0; i < elementCount; i++) { 
    // read elements 
} 
+0

vâng, tôi có thể sử dụng điều đó nhưng sẽ bất tiện hơn đề xuất của @yogendra singh –

+0

@Jon yeah, nó không an toàn (tệp có thể trống ...), chỉ được hiển thị dưới dạng thay thế – Katona

0

Đặt mã của bạn bên trong khối try catch: ví dụ:

try{ 
    if(in.available()!=0){ 
    // ------ 
    } 
}catch(EOFException eof){ 
    // 
}catch(Exception e){ 
    // 
} 
}