2010-09-09 38 views
5

Tôi đã có một chương trình Writer viết một dòng văn bản vào một tệp, sau đó chờ cho đến khi người dùng truy cập trở lại trước khi nó viết một dòng khác và sau đó thoát ra. Chỉ sau đó là tập tin đã đóng. Mã này:Tại sao FileInputStream read() không chặn?

public class Writer { 

    Writer() { 
    } 

    public static String[] strings = 
     { 
      "Hello World", 
      "Goodbye World" 
     }; 

    public static void main(String[] args) 
     throws java.io.IOException { 

     java.io.FileOutputStream pw = 
      new java.io.FileOutputStream("myfile.txt"); 

     for(String s : strings) { 
      pw.write(s.getBytes()); 
      System.in.read(); 
     } 

     pw.close(); 
    } 
} 

Bắt đầu đầu tiên với:

java Writer

Sau đó, tôi cũng có một chương trình đọc mà nên (tốt tôi mong đợi) chặn miễn là văn bản về tệp chưa hoàn thành (tức là pw.close() chưa được gọi). Mã này:

public class ReaderFIS extends Object { 

    ReaderFIS() { 
    } 

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

     java.io.FileInputStream in = new java.io.FileInputStream("myfile.txt"); 

     int ch = -1; 
     while((ch = in.read()) >= 0) { 
     System.out.println("ch = " + ch); 
    } 
     System.out.println("Last ch = " + ch); 

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

Bắt đầu với:

ReaderFIS java

Bây giờ tôi mong đợi các read() để chặn sau khi đọc đầu tiên "Hello World" văn bản, trên cơ sở này trong tài liệu Javadoc:

Đọc một byte dữ liệu từ luồng đầu vào này. Phương thức này sẽ chặn nếu không có đầu vào nào. Thông qua: http://docs.oracle.com/javase/6/docs/api/java/io/FileInputStream.html#read()

Nhưng ReaderFIS được thực hiện ngay sau khi đọc "Hello World" và dường như thấy EOF! Vì vậy, nó không phải khối! Nó đổ các giá trị ký tự, sau đó là -1 và sau đó in "thoát".

Output: ch = 72 ch = 101 ch = 108 ch = 108 ch = 111 ch = 32 ch = 87 ch = 111 ch = 114 ch = 108 ch = 100 Cuối cùng ch = -1 thoát

Các biến thể khác mà tôi đã thử là: đọc qua getChannel(), kiểm tra qua getChannel() nếu nó có thể được khóa() ed, using available(), try read() bằng cách sử dụng đệm, cố gắng readLine(), liên tục viết một char acter trong tập tin với một tạm dừng 500msec ở giữa mỗi viết, không viết bất cứ điều gì chỉ cần giữ các tập tin mở trong Writer.
Không có biến thể nào trong số này làm cho chương trình ReaderFIS chặn, nó luôn luôn kết thúc.

Tại sao chương trình người đọc không chặn? Tôi đã bỏ lỡ một cái gì đó soooo rất rõ ràng? Có vẻ như chương trình ReaderFIS tìm thấy một EOF (-1) nhưng tại sao? Tệp chưa được đóng bởi chương trình Writer.

Phụ trang "vui nhộn": System.in.read() đang chặn! (và chờ người dùng nhấn Enter).

PS: đã dùng thử trên Windows XP và Suse Linux. Trên Windows, tôi không thể xóa tệp trong khi người viết đang chạy (như tôi mong đợi).

Trân trọng, Marco

+0

khi bạn ghi vào đĩa bạn buộc EOF, không? EOF chỉ được di chuyển khi bạn thêm thông tin mới. Nhưng khối trên đĩa phải có một EOF ... – jcolebrand

+0

Vì vậy, bạn đang nói EOF là * luôn luôn * bằng văn bản bởi vì một tập tin luôn luôn cần một. Nhưng tôi nghĩ rằng một EOF chỉ được viết vào cuối sau khi xả và đóng tập tin. Nhưng điều đó có nghĩa là read() của tôi sẽ không bao giờ chặn khi đọc một tệp vì luôn có * một EOF và luôn trả về -1 ngay cả khi tệp rỗng. Vì vậy, JavaDoc không chính xác? – QQQuestions

Trả lời

0

bạn không hề nắm bắt những gì đang chặn. Chặn IO là lệnh chặn thực thi chương trình cho đến khi kết thúc thao tác IO. close chỉ ngắt kết nối chương trình khỏi tệp. Nếu bạn muốn một ứng dụng chặn một ứng dụng khác, bạn nên sử dụng một số loại đồng bộ hóa.

+0

Tôi không thực sự hiểu những gì bạn đang nói ở đây. – QQQuestions

+0

@qqquestions ok. Giả định này: "Sau đó, tôi cũng có một chương trình đọc mà nên (tôi mong đợi) khối miễn là văn bản của tập tin chưa hoàn thành (tức là pw.close() chưa được gọi)." là hoàn toàn không chính xác. Reader/writer không chặn lẫn nhau. (Chỉ trong trường hợp bạn cố gắng để đọc/ghi tập tin duy nhất đồng thời, nhưng không phải là trường hợp ở đây). google "không chặn io trong java", bạn sẽ tìm thấy các bài viết giải thích câu trả lời của tôi chi tiết. – Andrey

+0

Tại sao bạn nói 2 chương trình của tôi không đọc/ghi cùng một tệp đơn cùng một lúc? Hay bạn có nghĩa là * chính xác * cùng một lúc?Tôi googled cho các từ khóa được đề xuất của bạn nhưng điều đó cung cấp cho tôi không có thông tin chi tiết mới, chỉ các lần truy cập giải thích những gì không chặn IO. Bạn đang nói rằng nhà văn và người đọc của tôi là nonblocking? Nhưng tại sao JavaDoc sau đó nói đọc() nên được chặn ("Phương pháp này chặn nếu không có đầu vào là có sẵn") và làm thế nào nó thậm chí có thể được đọc các tập tin trong khi nó không có EOF bằng văn bản chưa? Và tôi * muốn * read() của tôi để chặn như Java Doc nói nó nên, tôi không muốn không chặn IO. – QQQuestions

1

Chương trình trình đọc của bạn sẽ chỉ đọc bất kỳ nội dung gì trong tệp, sau đó nhấn kết thúc và trả về -1. Nếu tất cả nó chứa tại thời điểm bạn chạy nó là "Hello World", thì đó là tất cả những gì nó có thể đọc được. Nếu bạn chạy nó một lần nữa sau khi bạn nhấn enter trong nhà văn của bạn, bạn sẽ thấy "Hello World Goodbye World".

Không còn byte nào và nhấn vào cuối luồng là hai điều khác nhau. Đó là lý do tại sao các khối System.in.read() và FileInputStream.read() thì không.

+0

Bạn có nói rằng phần đọc của tôi() ở cuối luồng không? Tại sao nó? Writer vẫn ở đó và mở tập tin/luồng. Và những gì sẽ là một ví dụ khi FileInputStream.read() sẽ chặn? Ví dụ mã sẽ là tuyệt vời ... – QQQuestions

+0

Đó là chính xác những gì tôi đang nói. Tôi không thể tưởng tượng FileInputStream.read() sẽ bao giờ chặn một lượng thời gian đáng kể cho một tập tin địa phương đọc. Chặn là một thứ thường xảy ra trên các loại InputStream khác, đó là sự trừu tượng của những thứ có độ trễ cao hơn (đọc socket, v.v.). – Seth

+0

Vì vậy, Javadoc là không chính xác? Nó nói nó sẽ chặn cho FileInputStreams. – QQQuestions

1

FileInputStream luôn có sẵn đầu vào: có byte để đọc hoặc có EOF, nhưng nói chung nó sẽ không chặn khi đọc. Bạn có thể bị chặn khi bạn là:

  • đọc từ một giao diện điều khiển/thiết bị đầu cuối
  • đọc từ mạng
  • đọc từ một ống
  • đọc từ bất cứ dòng đó là chờ cho dữ liệu.

file Streams không cần phải chờ đợi dữ liệu như họ luôn có dữ liệu có sẵn: trong trường hợp của bạn read() sẽ nhận được, về cơ bản một cách ngẫu nhiên, một trong số:

  • phiên bản cũ của tập tin
  • phiên bản mới của tệp
  • phiên bản được cập nhật một nửa của tệp.
+0

Vì vậy, bạn cũng ngụ ý Javadoc là không chính xác, * File * InputStreams sẽ không bao giờ chặn trên một đọc? – QQQuestions

+1

Không, javadoc nói rằng InputStreams sẽ chặn * nếu dữ liệu đầu vào không khả dụng *. Những gì tôi đang nói là FileInputStreams luôn có sẵn đầu vào, và vì vậy, theo javadoc, chúng không cần phải chặn. Về mặt kỹ thuật, chúng có thể vẫn chặn trong một số trường hợp góc, chẳng hạn như đọc từ một tệp có 'FileLock', nhưng điều đó dường như không phải là trường hợp này. – gpeche

+0

Gọi cho tôi cầu kỳ, nhưng sau đó các tài liệu nên nói rằng, bây giờ nó có thể được đọc (bởi tôi :) vì nó luôn luôn chặn nếu không có đầu vào có sẵn nào được nêu ra. Tôi ngạc nhiên rằng nó nhìn thấy một EOF trước khi tập tin được đóng lại, nhưng rõ ràng (theo nhận xét đầu tiên của bài viết gốc của tôi), sẽ luôn có một EOF và do đó có thể luôn luôn được đọc. – QQQuestions

0

Bạn không thể sử dụng tệp làm đường ống.

Tuy nhiên bạn có thể sử dụng ống làm đường ống.

+0

Có, tôi đoán hành vi tôi đang tìm là hành vi đường ống. Nhưng câu hỏi của tôi là tại sao nó không chặn, trong khi Javadoc nói nó chặn ... – QQQuestions

+0

Có phải không? Nó nói ở đâu? – EJP

+0

Xem bài đăng đầu tiên của tôi: Đọc một byte dữ liệu từ luồng đầu vào này. Phương thức này sẽ chặn nếu không có đầu vào nào. Qua: http://download-llnw.oracle.com/javase/6/docs/api/java/io/FileInputStream.html#read%28%29 – QQQuestions

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