2010-09-09 5 views
5

Ich habe ein Writer-Programm, das eine Textzeile in eine Datei schreibt und dann wartet, bis der Benutzer zurückkehrt, bevor er eine andere Zeile schreibt und dann beendet wird. Erst danach wird die Datei geschlossen. Der Code:Warum wird der FileInputStream read() nicht blockiert?

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

beginnen zuerst mit:

java Writer

Dann habe ich auch ein Leseprogramm haben, das sollte (auch ich erwartet hatte) blockieren, solange das Schreiben der Datei ist noch nicht fertig (dh p.close() wurde noch nicht aufgerufen). Der Code:

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

beginnen mit:

java ReaderFIS

Jetzt habe ich die Lese erwartet() zu blockieren, nachdem die erste "Hallo Welt" Text zu lesen, auf dieser Basis in die Javadoc-Dokumentation:

Liest ein Datenbyte aus diesem Eingabestream. Diese Methode blockiert, wenn noch keine Eingabe verfügbar ist. Via: http://docs.oracle.com/javase/6/docs/api/java/io/FileInputStream.html#read()

Aber die ReaderFIS werden sofort nach der Lektüre „Hallo Welt“ gemacht und sieht offenbar einen EOF! So ist es nicht Block! Es gibt die Zeichenwerte aus, dann eine -1 und dann "Beenden".

Output: ch = 72 ch = 101 ch = 108 ch = 108 ch = 111 ch = 32 ch = 87 ch = 111 ch = 114 ch = 108 ch = 100 Last ch = -1

Andere Variationen Verlassen habe ich versucht wurden: über eine getChannel Lesung(), über getChannel Überprüfung(), wenn es Sperre sein kann() ed, mit den verfügbaren() lesen Der Versuch() mit einem Puffer, versucht readLine(), kontinuierlich ein Zeichen zu schreiben Geben Sie in der Datei eine Pause von 500 ms zwischen den einzelnen Schreibvorgängen ein, und schreiben Sie nichts, sondern halten Sie die Datei im Writer offen.
Keine dieser Variationen bewirkt, dass das ReaderFIS-Programm blockiert, es wird immer beendet.

Warum blockiert das Leseprogramm nicht? Habe ich etwas so offensichtlich übersehen? Es scheint, dass das ReaderFIS-Programm einen EOF (-1) findet, aber warum? Die Datei wurde vom Writer-Programm noch nicht geschlossen.

"Lustige" Nebenbemerkung: Die System.in.read() blockiert! (und darauf warten, dass der Benutzer Enter drückt).

PS: versuchte dies unter Windows XP und Suse Linux. Unter Windows kann ich die Datei nicht löschen, während der Schreiber läuft (was ich erwartet habe).

Grüße, Marco

+0

Wenn Sie auf Festplatte schreiben, erzwingen Sie einen EOF, nein? Der EOF wird nur verschoben, wenn Sie neue Informationen anhängen. Aber der Block auf der Platte muss einen EOF haben ... – jcolebrand

+0

Sie sagen also, der EOF wird * immer * geschrieben, weil eine Datei immer einen braucht. Aber ich dachte, ein EOF wird nur am Ende geschrieben, nachdem die Datei gespült und geschlossen wurde. Aber das bedeutet, dass mein read() niemals beim Lesen einer Datei blockiert, weil es * immer * ein EOF gibt und immer ein -1 zurückgibt, selbst wenn die Datei leer ist. Also ist das JavaDoc inkorrekt? – QQQuestions

Antwort

0

Sie nicht leicht fangen, was blockiert wird. Das Blockieren von IO blockiert die Ausführung des Programms, bis der IO-Vorgang beendet ist. close trennen Sie einfach das Programm von der Datei. Wenn Sie möchten, dass eine App eine andere blockiert, sollten Sie eine Art Synchronisation verwenden.

+0

Ich verstehe nicht wirklich, was Sie hier sagen. – QQQuestions

+0

@qqquestions ok. Diese Annahme: "Dann habe ich auch ein Leseprogramm, das (wohl ich erwarte) blockieren sollte, solange das Schreiben der Datei noch nicht beendet ist (d. H. P.close() wurde noch nicht aufgerufen)." ist völlig inkorrekt. Reader/Writer blockieren sich nicht gegenseitig. (Nur für den Fall, dass Sie versuchen, eine einzelne Datei gleichzeitig zu lesen/zu schreiben, ist dies jedoch nicht der Fall). Google "non blocking io in Java", finden Sie Artikel, die meine Antwort im Detail erklären. – Andrey

+0

Warum sagen Sie, dass meine 2 Programme nicht gleichzeitig dieselbe Datei lesen/schreiben? Oder meinst du * genau * gleichzeitig?Ich habe nach den vorgeschlagenen Keywords gegoogelt, aber das hat mir keine neuen Erkenntnisse gebracht, sondern nur Treffer, die erklären, was nicht blockierendes IO ist. Sagst du, mein Autor und Leser sind nicht blockierend? Aber warum sagt das JavaDoc dann, dass read() blockiert werden sollte ("Diese Methode blockiert, wenn noch keine Eingabe verfügbar ist") und wie kann es sogar die Datei lesen, während noch kein EOF geschrieben wurde? Und ich * will * myread() blockieren, wie es im Java-Doc heißt, ich will keine nicht blockierende IO. – QQQuestions

1

Ihr Leser-Programm wird nur lesen, was in der Datei ist, dann drücken Sie das Ende und geben -1 zurück. Wenn alles zu dem Zeitpunkt, an dem Sie es ausführen, "Hello World" enthält, dann ist es alles, was es lesen kann. Wenn Sie es erneut ausführen, nachdem Sie in Ihrem Writer auf Enter geklickt haben, sollten Sie "Hello World Goodbye World" sehen.

Da keine Bytes mehr verfügbar sind und das Ende eines Streams erreicht wird, gibt es zwei verschiedene Dinge. Deshalb blockiert System.in.read() und FileInputStream.read() nicht.

+0

Sagst du, dass meine read() am Ende des Streams ist? Warum sollte es sein? Der Writer ist immer noch da und die Datei/der Stream ist geöffnet. Und was wäre ein Beispiel, wenn FileInputStream.read() blockieren würde? Beispielcode wäre toll ... – QQQuestions

+0

Genau das sage ich. Ich kann mir nicht vorstellen, dass FileInputStream.read() jemals für eine lokale Datei lesen wird. Das Blockieren wird normalerweise bei anderen Arten von InputStreams passieren, bei denen es sich um Abstraktionen von Objekten mit höherer Latenz handelt (Socket-Lesevorgänge usw.). – Seth

+0

Also ist der Javadoc falsch? Es sagt, es wird für FileInputStreams blockieren. – QQQuestions

1

FileInputStream hat immer eine Eingabe zur Verfügung: Entweder sind noch Bytes zum Lesen vorhanden oder es gibt ein EOF, aber im Allgemeinen wird es beim Lesen nicht blockiert.

  • von einer Konsole/Leseterminal
  • Lesen aus dem Netzwerk
  • aus einem Rohr Lesen
  • Lesen aus welchem ​​Strom, der auf Daten warten ist: Sie können, wenn Sie sind blockiert werden.

Datei-Streams müssen nicht auf Daten warten, da sie immer Daten zur Verfügung: in Ihrem Fall read() erhalten, grundsätzlich nach dem Zufallsprinzip, von:

  • die alte Version der Datei
  • die neue Version der Datei
  • halb aktualisierte Version der Datei.
+0

Sie impliziert also auch, dass Javadoc falsch ist, * Datei * InputStreams wird bei einem Lesevorgang niemals blockieren? – QQQuestions

+1

Nein, javadoc sagt, dass InputStreams * blockiert, wenn Eingabedaten nicht verfügbar sind *. Was ich sagen will, ist, dass FileInputStreams immer eine Eingabe zur Verfügung hat und sie daher laut javadoc nicht blockieren müssen. Technisch gesehen könnten sie in einigen Fällen noch blockieren, wie zum Beispiel das Lesen von einer Datei mit einer 'FileLock', aber das scheint nicht der Fall zu sein. – gpeche

+0

Nennt mich wählerisch, aber dann sollte die Dokumentation das gesagt haben, jetzt kann es (von mir :) gelesen werden, da es immer blockiert, wenn noch keine Eingabe möglich ist. Ich bin überrascht, dass es vor dem Schließen der Datei ein EOF sieht, aber anscheinend (wie beim allerersten Kommentar meines ursprünglichen Beitrags) wird es immer ein EOF geben, das man immer lesen kann. – QQQuestions

0

Sie können Dateien nicht als Pipes verwenden.

Sie können jedoch Rohre als Rohre verwenden.

+0

Ja Ich denke, das Verhalten, das ich suche, ist Pipe-Verhalten. Aber meine Frage ist, warum es nicht blockiert, während der Javadoc sagt, dass es blockiert ... – QQQuestions

+0

Tut es? Wo sagt es das? – EJP

+0

Siehe meinen ersten Post: Liest ein Datenbyte aus diesem Eingabestream. Diese Methode blockiert, wenn noch keine Eingabe verfügbar ist. Via: http://download-llnw.oracle.com/javase/6/docs/api/java/io/FileInputStream.html#read%28%29 – QQQuestions