Was ist das letzte Zeichen in einer Datei?

19

Ich habe gerade die Antworten zu "Entfernen eines Newline-Zeichens am Ende einer Datei" gelesen und alle sagten, dass sie das letzte Zeichen löschen sollen. Meine Frage ist, ist der eof Charakter nicht der letzte?

Sworwitz
quelle
11
EOF ist kein Charakter .
Soren Bjornstad
1
@SorenBjornstad Ich möchte auch hinzufügen, dass eine neue Zeile am Ende einer Unix-Textdatei dort steht, weil sie die letzte Zeile beendet. Eine leere Textdatei hat am Ende keine neue Zeile: Sie besteht aus einer Folge von Null Zeichen.
Kaz
3
Um etwas umständlich zu sein, haben CPM und DOS ^ Z als EOF-Zeichen verwendet, und es kann immer noch vorkommen, dass Sie auf Dateien stoßen, die mit ^ Z enden.
Edward Falk

Antworten:

13

Eine Datei endet nicht mit einem Dateiende-Zeichen, wie in den vorherigen Antworten korrekt angegeben. Aber ich denke, die Antworten und Kommentare enthalten einige Ungenauigkeiten, auf die es sich hinzuweisen lohnt:

  • Der ASCII-Zeichensatz enthält kein genaues EOF-Zeichen. Es gibt mehrere Steuerzeichen für "Ende": Textende (3), Übertragungsende (4), Übertragungsende-Block (23), Medienende (25). File Separator (28) kommt einem EOF-Zeichen möglicherweise am nächsten. Code 26 ist "Ersatz", nicht EOF.

  • Ctrl- Dist nur mit dem Klemmeneingang verbunden. Zum Beispiel beinhaltet der Befehl cat filea fileb filec > outfilenicht Ctrl- D. Übrigens können Sie das EOF-Zeichen des Terminals in etwas anderes ändern als Ctrl- Dmit dem sttyBefehl.

  • Genau genommen ist Ctrl- D(oder was auch immer Sie geändert haben) kein EOF-Schlüsselcode. Dies bewirkt, dass der readSystemaufruf mit den verfügbaren Eingaben zurückgegeben wird. Ebenso wie das Drücken der Eingabetaste bewirkt, dass der gelesene Systemaufruf eine Zeile mit Zeichen an den Aufrufer zurückgibt. Gemäß der Konvention signalisiert ein Rückgabewert von Null aus dem Lesesystemaufruf (dh Null gelesene Zeichen) ein Ende der Dateibedingung. Die Eingabedatei wird jedoch nicht automatisch geschlossen, und wenn die Eingabe vom Terminal stammt, wird sie nicht in den Status "Dateiende" versetzt. Sie können ein Programm schreiben, das auch nach einem "Dateiende" weiter vom Terminal liest, und der Leseaufruf kann für die nächste Eingabezeile ungleich Null zurückgeben.

  • Die Analogie zwischen den Zeichen eof und eol wird sichtbar, wenn Ctrl- Dgedrückt wird, wenn bereits eine Eingabe in die Zeile geschrieben wurde. Wenn Sie beispielsweise "abc" schreiben und die Taste drücken Ctrl- Dder Leseaufruf wird zurückgegeben, diesmal mit einem Rückgabewert von 3 und mit "abc", das im als Argument übergebenen Puffer gespeichert ist. Da read nicht 0 zurückgibt, wird dies gemäß der obigen Konvention nicht als EOF-Bedingung interpretiert. Wenn Sie die Eingabetaste drücken, kehrt der gelesene Anruf mit der gesamten Eingabezeile (einschließlich der neuen Zeile) zurück. Sie können dies mit dem catBefehl ausprobieren : Schreiben Sie einige Zeichen in die Zeile und drücken Sie Ctrl- D. Sie werden sehen, wie die Zeichen zu Ihnen zurückkehren und catauf weitere Eingaben warten.

  • All dies gilt nur, wenn sich das Terminal im Modus "Gekocht" befindet, im Gegensatz zum Modus "Roh", in dem die Verarbeitung der Zeileneingabe minimiert ist. Im Raw-Modus wird tatsächlich ein Strg-D-Zeichen an den Eingabepuffer übergeben.

Johan Myréen
quelle
19

ASCII-Steuerzeichen haben Definitionen aus den 1960er Jahren (tatsächlich vor dem, was Sie als Netzwerk betrachten ). Nicht alle dieser Steuerzeichen werden so verwendet, wie sie damals für Telekommunikationsgeräte definiert waren.

Auf Unix-ähnlichen Systemen ist kein EOFZeichen erforderlich . es wird keiner verwendet. Das System kann Anwendungen mitteilen, wie viele Bytes sich in einer Datei befinden:

  • Auf einigen anderen Systemen (in VMS, DOS, Windows) fungiert ein Control-Z möglicherweise als Dateiendemarker, da das System in älteren Versionen einigen Anwendungen nicht mitteilen konnte, wie viele Bytes sich in der Datei befinden.

    Bei VMS lag die Einschränkung in der Funktionsweise der C-Laufzeit. Assembler-Anwendungen konnten (und haben) die richtige Dateigröße erhalten.

  • Unix-Systeme in der Shell verwenden herkömmlicherweise Control-D, um einer Anwendung mitzuteilen, dass das Ende der Eingabe (Datei) erreicht wurde, das Control-D jedoch nicht in der Datei gespeichert ist.

In C EOFwird bewusst -1darauf hingewiesen, dass es sich nicht um ein gültiges Zeichen handelt. Standard-E / A wird zurückgegeben, EOFwenn eine Dateiende-Bedingung erkannt wird - kein Sonderzeichen.

Dateien müssen übrigens nicht mit einem Zeilenumbruch (ASCII-Zeilenvorschub) enden . Texteditoren können mit Dateien umgehen, bei denen es sich ausschließlich um druckbaren Text handelt, für die jedoch keine abschließende Zeile vorhanden ist.

Thomas Dickey
quelle
8
POSIX definiert eine Textdatei als eine Datei, die eine Folge von Zeilen enthält, und jede Zeile wiederum als Folge von Nicht-Zeilenumbruchzeichen, gefolgt von einer neuen Zeile. Daher ist eine Datei, die mit etwas anderem als 0x0A endet, keine konforme Textdatei.
Damian Yerrick
2
Ich bin mir dessen bewusst, weshalb ich darauf hingewiesen habe, dass Texteditoren funktionieren. (Binärdateien unterliegen keiner solchen Einschränkung).
Thomas Dickey
Es ist wirklich erwähnenswert, dass Dateien, die als Text ohne abschließende Zeilenumbrüche behandelt werden sollen, immer noch eine schlechte Form haben (selbst wenn typische Texteditoren zum Kompensieren solcher Dateien codiert wurden), zumindest wenn Sie dies tatsächlich möchten im Großen und Ganzen benutzerfreundlich / kompatibel, da das Fehlen eines newline zusätzliche Schwierigkeiten hinzufügen können unter verschiedenen Umständen (verketten / Drucken mehrerer Textdateien, Parsing mit typischen Kommandozeilen - Tools, minimal - Editoren wie busybox‚s vi, etc).
Mtraceur
(1) Vor VMS verfügte RT-11 RSX-11 TOPS-10 über nur blockgenaue Dateisysteme und benötigte ein EOF-Zeichen. CP / M kopierte es anscheinend von DEC und wurde von MS-DOS kopiert und dann an Windows weitergegeben. (2) Unter Unix ist es der tty-Treiber, nicht die Shell, wie es von JohanM ausführlicher beschrieben wird, obwohl die Leute normalerweise Shells auf tty-Geräten ausführen.
Dave_thompson_085
Sicher - DEC war wieder da (und beachte, dass ich ältere Versionen erwähnt habe). Ob dies der Ursprung des CP / M-Features war, wäre ein interessantes Thema (nicht hier). Ich erwähnte diese Fälle, um die Alternativen zu erläutern.
Thomas Dickey
7

EOF ist kein Charakter. Dies ist ein Status, der angibt, dass keine Zeichen mehr aus einem Dateistream gelesen werden müssen. Wenn Sie den EOF-Befehl über das Terminal eingeben, signalisieren Sie dem Betriebssystem, den Eingabestream zu schließen, ohne ein Sonderzeichen einzugeben.

Munir
quelle
1
Ja, aber in der ASCII-Tabelle ist EOF 26, also dachte ich, das letzte Byte sei die Binärdarstellung von 26. Wie kann ein Programm, das eine Eingabe liest, wissen, wo sie endet?
Sworwitz
ASCII war für die Weitergabe von Informationen über ein Netzwerk gedacht. In diesem Fall benötigen Sie ein EOF-Zeichen. (ASCII hatte auch viele Steuercodes. Nicht alles war druckbar.) Bei Dateistreams ist die Größe der Datei bereits über das Dateisystem bekannt, sodass das Betriebssystem erkennen kann, wenn keine Daten mehr zu lesen sind.
Munir
@sworwitz: In Bezug auf C geben Eingabelesefunktionen, die ein Zeichen pro Aufruf zurückgeben, ein int (normalerweise eine 32-Bit-Zahl, aber mindestens 16 Bit) und kein char zurück. Die Funktion signalisiert und EOF, indem sie -1 (0xffffffff) zurückgibt, was kein gültiger 8-Bit-Wert ist, sodass es nicht durch ASCII-Zeichen verwechselt wird, auch nicht durch 0xff. Funktionen, die eine Zeichenfolge zurückgeben, geben auch die Länge der gelesenen Daten zurück. Diese Länge kann verwendet werden, um keine Daten oder kein Datenende zu signalisieren (wieder kann die Länge -1 sein). Schließlich gibt es noch eine Funktion, die Sie aufrufen können, um
festzustellen,
OK danke! Wenn ich also in der Bash die Tastenkombination Strg + D drücke, gebe ich bei der Eingabe das ASCII-Zeichen ein, oder?
Sworwitz
@sworwitz Nicht genau. Bevor bashder Eingang in die Hände kommt, wird er vom TTY-Fahrer massiert. Dieser Treiber fängt Strg-D ab und sendet ein EOF an bash (wobei EOF kein Zeichen, sondern ein spezieller Dateistatus ist)
Stig Hemmer,