2017-03-20 6 views
10

Liest eine Textzeile. Eine Zeile gilt als beendet, wenn ein Zeilenvorschub ('\ n'), ein Wagenrücklauf ('\ r') oder ein Wagenrücklauf, unmittelbar gefolgt von einem Zeilenvorschub, beendet wird. --- javadoc 1.8Warum BufferedReader.readLine eine Zeile lesen kann, die kein Zeilentrennzeichen enthält

Dann habe ich eine Textdatei wie folgt aus:

the first line 
the second line 

Anmerkung: das letzte Zeichen der seond Linie ist ‚e‘, die dort existieren Rückkehr Wagen nicht zu sagen ist.

dann hier ist mein Demo-Code.

public void process() throws IOException{ 
    BufferedReader br = new BufferedReader(new FileReader("demo.txt")); 
    String line; 
    while((line=br.readLine())!=null){ 
     System.out.println(line); 
    } 
    br.close(); 
} 

die reale Produktion:

the first line 
the second line 

dann Frage meine ist, warum die Methode Readline kann die zweite Zeile erhalten für sie Line-Trennzeichen (\ n oder \ r oder \ n \ doesnt haben r).
Ich weiß, gibt es eine Ende der Datei (EOF), aber es schien, dass die Javadoc nicht die EOF ist auch der Zeilentrenner explizit.

Wenn ich Scanner anstelle von BufferedReader den Code wie folgt:

public void testScan() throws IOException{ 
    Scanner scan = new Scanner(new FileInputStream("demo.txt")); 
    String line; 
    while((line=scan.nextLine())!=null){ 
     System.out.println(line); 
    } 
    scan.close(); 
} 

dann wäre der Ausgang sein:

the first line 
the second line 
Exception in thread "main" java.util.NoSuchElementException: No line found 
    at java.util.Scanner.nextLine(Scanner.java:1540) 
    at com.demo.Demo.testScan(Demo.java:39) 
    at com.demo.Demo.main(Demo.java:49) 

Antwort

9

Weil es auf diese Weise programmiert ist.

Wirklich, es ist, was der Benutzer der Methode will. Wenn in der letzten Zeile ein Zeilentrennzeichen am Ende fehlt, wird bis EOF gelesen, so dass keine Daten verloren gehen. Sie möchten wegen eines fehlenden Zeilentrenners keine ganze Zeile verlieren.

Praktisch alle ähnlichen Funktionen funktionieren in der gleichen Weise. Wenn Sie beispielsweise die Funktion fgets() in der C-Bibliothek betrachten, funktioniert das auch so. So auch f.readline() in Python.

Bearbeiten: der Scanner funktioniert auch in der gleichen Weise, aber der Unterschied ist, dass ein Scanner eine Ausnahme auslöst, während BufferedReader null zurückgibt, wenn alle Zeilen gelesen worden sind.

9

es schien der Javadoc nicht sagen, die EOF ist auch der Zeilentrenner explizit.

Ich glaube, Sie verwechseln Zeilentrenn mit Leitungsabschluss.

Ein Linienseparator trennt nur Linien voneinander. Wenn Sie ein Zeilentrennzeichen ; und einen Eingang one;two;three eingeben, erhalten Sie die Zeilen one, two und three. Wenn Sie jedoch das gleiche Zeichen und die gleiche Eingabe verwenden, aber ; ein Zeilenabschlusszeichen ist, erhalten Sie die Zeilen one und two, da die letzte Zeile nicht beendet wird.

In der Praxis bedeutet dies, dass, wenn EOF wirklich eine Linie Separator sein würde, Sie zusätzliche Daten bekommen würde. Da EOF technisch gesehen kein Zeichen ist, sondern eine Bedingung, dass die Datei beendet ist, hätte EOF als Zeilentrenner wilde Konsequenzen.

jedoch angesichts der javadoc:

Liest eine Textzeile. Eine Linie betrachtet wird durch eine einen Zeilenvorschub (‚\ n‘), ein Wagenrücklauf (‚\ r‘) oder eine Wagenrück unmittelbar gefolgt von einem Zeilenvorschub beendet werden.

Ich denke, Terminologie wird auch dort missbraucht. Entweder sollte das Javadoc über das Trennen sprechen, anstatt es zu beenden, es sollte EOF als eine der Bedingungen angeben, die die Zeile beenden, oder die Implementierung sollte das letzte nicht als separate Zeile behandeln.

Von Wikipedia:

Zwei Möglichkeiten Zeilenumbrüche, die beide in sich konsistent sind, dass newlines entweder getrennte Leitungen oder dass sie enden Linien zu sehen. Wenn ein Newline einen Separator betrachtet wird, wird es nach der letzten Zeile einer Datei kein Newline sein. Einige Programme haben Probleme beim Verarbeiten der letzten Zeile einer Datei, wenn sie nicht durch einen Zeilenumbruch beendet wird. Auf der anderen Seite Hand, Programme, die erwarten, Newline als Trennzeichen verwendet werden interpretieren eine letzte Newline als eine neue (leere) Linie zu starten. Umgekehrt wenn ein Newline ein Terminator in Betracht gezogen wird, werden alle Textzeilen einschließlich der zuletzt durch eine neue Zeile beendet werden zu erwarten. Wenn die letzte Zeichenfolge in einer Textdatei kein Zeilenumbruch ist, kann die letzte Zeile von die Datei als eine falsche oder unvollständige Textzeile, oder die Datei möglicherweise als nicht ordnungsgemäß abgeschnitten betrachtet werden.

So scheint es readLine() hat diese durcheinander.

IMO readLine() Javadoc- sollte etwas sagen:

Eine Linie betrachtet wird am Ende der Datei oder die durch einen Zeilenvorschub (‚\ n‘), ein Schlitten beendet werden return ('\ r'), oder ein Wagenrücklauf gefolgt von sofort durch einen Zeilenvorschub.

oder für ein bisschen mehr vageen Ausdruck, ähnlich das, was Scanner.nextLine() says:

Diese Methode gibt die [..] aktuelle Zeile, jede Zeile Separator am Ende ohne

Mit dem Zusatz, dass es null zurückgibt, wenn das Ende der Datei die einzige Eingabe ist, die dort gelassen wird.

Verwandte Themen