2010-09-09 114 views
5

我有一個Writer程序,它將一行文本寫入文件,然後等待用戶在寫入另一行之前先返回,然後退出。只有在文件關閉之後。代碼:爲什麼FileInputStream的read()沒有被阻塞?

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(); 
    } 
} 

開始先用:

java的作家

然後我也有應該(以及我的預期),一個閱讀器程序,只要塊作爲的寫作文件尚未完成(即pw.close()尚未被調用)。代碼:

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"); 
    } 
} 

開始:

的Java ReaderFIS

現在我預期的read()讀取第一個 「Hello World」 文本後的阻攔,基於此Javadoc文檔:

中讀取數據的從該輸入流的一個字節。如果沒有輸入可用,此方法會阻止。 途經:http://docs.oracle.com/javase/6/docs/api/java/io/FileInputStream.html#read()

但ReaderFIS正在讀的 「Hello World」,顯然後立即進行看到一個EOF!所以它不是塊!它轉儲字符值,然後是-1,然後打印「退出」。

輸出: CH = 72 CH = 101 CH = 108 CH = 108 CH = 111 CH = 32 CH = 87 CH = 111 CH = 114 CH = 108 CH = 100 最後CH = -1 離開

我試圖進行其它變化:經由getChannel()讀取,通過getChannel()檢查是否它可以是鎖()的,使用可用的(),試圖使用讀()緩衝區,嘗試readLine(),不斷寫入字符在每次寫入之間暫停500毫秒,不寫任何文件,只是在寫入器中保持文件打開。
這些變化都不會導致ReaderFIS程序阻塞,它總是結束。

爲什麼讀者程序不能阻止?我錯過了非常明顯的東西嗎?看來ReaderFIS程序找到EOF(-1),但爲什麼?該文件尚未被Writer程序關閉。

「有趣」的註釋:System.in.read()被阻止! (並等待用戶按Enter鍵)。 PS:在Windows XP和Suse Linux上試用過。在Windows上,我無法在編寫器運行時刪除文件(這是我的預期)。

問候, 馬爾科

+0

當你寫入磁盤時,你強制使用EOF,不是嗎? EOF僅在追加新信息時纔會移動。但是磁盤上的塊必須有一個EOF ... – jcolebrand 2010-09-09 15:10:46

+0

所以你說EOF總是被寫入,因爲一個文件總是需要一個。但我認爲EOF只是在沖洗和關閉文件後才寫完。但這意味着我的read()在讀取文件時永遠不會阻塞,因爲* always * EOF並且即使文件爲空也總是返回-1。那麼JavaDoc不正確? – QQQuestions 2010-09-09 16:29:07

回答

0

你稍微沒趕上什麼阻止。阻塞IO是阻止程序執行直到IO操作完成的程序。 close只是斷開與文件的程序。如果你想要一個應用程序阻止另一個應用程序,你應該使用某種同步。

+0

我真的不明白你在這裏說什麼。 – QQQuestions 2010-09-09 15:39:15

+0

@qqquestions好的。這個假設:「然後,我還有一個讀者程序,只要文件的寫入還沒有完成(即,pw.close()尚未被調用),就應該(只要我期望)阻止。」是完全不正確的。讀者/作家不會互相阻攔。 (只有在您嘗試同時讀取/寫入單個文件的情況下,情況並非如此)。谷歌「在Java中不封鎖io」,你會發現文章詳細解釋我的答案。 – Andrey 2010-09-09 16:02:45

+0

爲什麼你說我的2個程序不能同時讀/寫同一個文件?或者你的意思是*在同一時間?我搜索了你的建議關鍵字,但是這並沒有提供新的見解,只是解釋了什麼是非阻塞IO。你是說我的作家和讀者是無阻塞的嗎?但是,爲什麼JavaDoc會說read()應該被阻塞(「如果沒有輸入可用,這個方法會被阻塞」)以及它在沒有EOF寫入的情況下如何讀取文件?我希望我的read()能夠像Java Doc所說的那樣阻塞,我不希望非阻塞IO。 – QQQuestions 2010-09-09 16:23:26

1

您的讀者程序只是讀取文件中的任何內容,然後點擊結尾並返回-1。如果它在運行時包含的是「Hello World」,那麼它就可以讀取。如果您在作家中輸入後再次運行,您應該看到「Hello World Goodbye World」。

沒有更多的字節可用,並打到一個流結束是兩個不同的東西。這就是爲什麼System.in.read()塊和FileInputStream.read()沒有。

+0

你是說我的read()在流的末尾?爲什麼會這樣? Writer仍然在那裏,文件/流打開。什麼是FileInputStream.read()將阻止的例子?示例代碼將很棒... – QQQuestions 2010-09-09 15:35:38

+0

這正是我所說的。我無法想象FileInputStream.read()會永久阻塞本地文件讀取的大量時間。阻塞通常會發生在其他類型的InputStream上,這些InputStream是抽象延遲較高的事物(套接字讀取等)。 – Seth 2010-09-09 18:50:19

+0

所以Javadoc不正確?它說它會阻塞FileInputStreams。 – QQQuestions 2010-09-13 08:46:48

1

FileInputStream始終有可用的輸入:要麼有剩餘的字節要讀取,要麼有EOF,但通常讀取時不會阻塞。你可能被阻止,當你:

  • 從一個控制檯/終端
  • 從網絡
  • 從管道
  • 從是等待數據無論流中讀取讀取讀取讀取。

文件流不必等待數據,因爲他們總是有可用的數據:在你的情況read()會得到,基本上隨機,之一:舊版本的文件

  • 文件的新版本
  • 文件的一半更新版本。
+0

所以你也暗示Javadoc是不正確的,* File * InputStreams永遠不會阻止讀取? – QQQuestions 2010-09-13 08:49:48

+1

不,javadoc說如果輸入數據不可用,InputStreams會阻塞*。我所說的是FileInputStreams總是有可用的輸入,所以根據javadoc,它們不需要阻塞。從技術上講,它們可能會在某些角落案例中阻塞,例如使用'FileLock'從文件中讀取數據,但似乎並不是這種情況。 – gpeche 2010-09-13 10:01:43

+0

給我打電話挑剔,但那麼文檔應該說,現在它可以閱讀(由我:),因爲它總是阻塞,如果沒有可用的輸入。我很驚訝它在文件關閉之前看到了一個EOF,但顯然(根據我原始文章的第一條評論),總是會有一個EOF,因此總是可以閱讀。 – QQQuestions 2010-09-13 13:27:53

0

您不能將文件用作管道。

但是,您可以使用管道作爲管道。

+0

是的,我想我正在尋找的行爲是管道行爲。但我的問題是爲什麼它不阻止,而Javadoc說它阻止... – QQQuestions 2010-09-13 08:48:12

+0

是嗎?它在哪裏說呢? – EJP 2010-09-13 09:04:37

+0

看我的第一篇文章:從這個輸入流中讀取一個字節的數據。如果沒有輸入可用,此方法會阻止。通過:http://download-llnw.oracle.com/javase/6/docs/api/java/io/FileInputStream.html#read%28%29 – QQQuestions 2010-09-13 13:22:18

相關問題