Leidiges Thema Editor und Zeilenumbruch bzw. Zeilenende.

PHuV

Banned
Registriert
März 2005
Beiträge
14.219
Ich muß gerade nach jahrelanger Nutzung mit Notepad++ feststellen, daß dieser Editor Dateien nicht explizit mit einem Zeilenende (Windows 0d0a /r/n bzw. Carriage Return/Linefeed, und unter UNIX 0a /n bzw. Linefeed) abschließt. Andere Editoren wie Windows Editor bzw. Notepad speichert auch kein Dateiende. Als langjähriger vi-Benutzer bin ich es eigentlich gewohnt, daß ein Editor eine Datei immer korrekt abschließt. Sprich, selbst wenn man am Zeilenende ist, und kein Return drückt, findet sich am Ende ein 0a. Genauso arbeiten die Editoren unter UINX/Linux hier korrekt, es findet sich immer ein Zeilenende als Dateiabschluß.

Dadurch, daß ich selten Daten mit einem Windows Editor erzeuge, ist mir das so noch nicht aufgefallen. Sonst erzeuge ich CSV und Co generativ mit Unix/Linux Befehlen oder unter Windows mit Cygwin\CMD. Hier arbeitet Windows auch korrekt, in
Code:
echo "Hallo" >C:\test.txt
findet sich in der Datei ein einwandfreies 0d0a.

Warum ist das so? Eine übliche Textdatei ohne ein Zeilenende ist doch nach meinem bisherigen Verständnis ein inkonsistenter Zustand, siehe auch Definition Zeilenumbruch? Alle entsprechenden Programmiersprachen und APIs, die zeilenweise einlesen und mit den Zeilenende rechnen müssen, haben dann ein Problem, siehe Beispiel:
Code:
[root@host~]# cat test5.txt
test1
test2
test3[root@host~]# while read a
> do
> echo $a
> done <test5.txt
test1
test2
[root@host~]#
Es fehlt der letzte Wert in der Zeile. Jeder, der mal nativ Dateien einlesen mußte (C, C++, Java...) und sich mit fseek und Co. rumplagen mußte, weiß ja, daß wenn kein expliziter Zeitentrenner vorhanden ist, viele C-Leseroutinen und -abfragen ganz einfach fehlschlagen.

Das Problem ist jetzt mal hochgekocht, weil ein Kollegen die Dateien per Hand in einem Editor änderte, und vergaß, am Zeilenende nochmal eine Return einzufügen. Das passiert an sich immer nur Windows-Kollegen, und EMACS-Nutzern :p unter Unix.

Wie seht Ihr das? BTW habe ich im Notepad++ auf die Schnelle keine Option gefunden, explizit einen Zeilentrenner am letzten Zeichen der Datei zu erzwingen.
 
txt != txt
da gibt es unterschiedliche formatierungen und codierungen. aber notepad++ kann damit um
wenn man nen unix/linux file öffnet und die absatzzeichen einblendet, sieht man dass es nur nen linefeed gibt und bei windows files wird am ende jeder zeile ein linefeed und ein carriage return angezeigt.
2019-02-25 17_41_29-Window.png
2019-02-25 17_41_12-Window.png


Wo man es jedoch beim erstellen einer neuen datei umstellt weiss ich aus dem stehgreif nicht mehr. habs ewig nicht gebraucht :)

EDIT: Hier müsstest du fündig werden:
https://superuser.com/questions/120...e-returns-are-added-to-notepad-documents?rq=1
 
Ich bin der Meinung, notepad++ bietet so eine Option, beim Speichern einen Zeilenumbruch einzufügen, falls es noch keinen gibt. Ad hoc kann ich dir aber nicht sagen, wo man das einstellt. Irgendwo bei den Einstellungen für Dateitypen, denke ich.

Ansonsten sehe ich das so: erfordert dein Datenformat zwingend ein abschließendes Zeilenendezeichen, musst du es setzen. Das kann der Editor erstmal nicht wissen. Ein Programm, das ungefragt meine Daten verändert, die ich willentlich und wissentlich exakt so eingegeben habe, käme mir jedenfalls nicht ins Haus.
 
Nunja,

Es gibt ja einige Philosophie- Unterschiede zwischen der Unix-/Linux- und der Windows- Welt.
Aber auf einen fehlenden Zeilenumbruch am Ende einer Textdatei hatte ich noch nie geachtet.

Technisch gesehen arbeiten beide Editoren in meinen Augen korrekt:
  • vi ist ein zeilenbasierter Editor. Demnach braucht jede Zeile auch ein Carriage Return am Zeilenende, sonst ist sie nicht komplett.
  • Notepad++ oder Emacs hingegen arbeiten anders. Da wäre jedes Zeichen, daß der Editor ohne Wissen des Nutzers in der Datei einfügt ein Fehler. So wie es auch @KillerCow schreibt, das ist Veränderung der Daten, das geht gar nicht.
  • Interessant wäre, wie sich andere verbreteitete Editoren unter Linux verhalten. Nano zum Beispiel. Fügt der auch eine Leerzeile ein beim Speichern?

Aber das kann leider wohl nur der Empirie dienen. Denn selbst wenn es eine Einstellung im Notepad++ gibt, immer einen Zeilenumbruch mitzuspeichern, wirst Du Dich nicht drauf verlassen können, daß das jeder Deiner Kollegen setzt oder auch daß jeder den N++ nutzt.

Du wirst wohl nicht drumrum kommen, die Datei vor dem Verarbeiten auf ein Carriage Return am Ende zu prüfen und im Fall das es fehlt eins anzuhängen.

Ich fürchte, genau wegen solcher Schwierigkeiten hat man vor knapp 20 Jahren begonnen, Austauschformate wie XML oder JSON zu spezfizieren, die sich nicht durch solche "Formunvollkommenheiten" aus der Bahn werfen lassen.
 
Es gibt \n, es gibt \r\n und Mac nutzt(e?) \r. Ist halt so. Eine Leerzeile am Ende der Datei ist auch historisch bedingt. Es muss aber Keines enthalten sein.
 
Es muß keines enthalten, wenn Du per Zeilenlänge, wie bei Fixformaten, die Daten über feste Positionen feststellen kannst. Bei variablen Datenfelder braucht es immer einen Trenner, und bei Zeilen ebenso. Alle mir bekannten APIs und Programmierfunktionen arbeiten so, daß Dateien mit EOF und Zeilentrenner arbeiten. Da EOF kein festgelegten Zeichen ist, ist das per se der letzten Zeilentrenner innerhalb einer Datei.

@rocketworm
Genau das ist ja der Kniff, laß man am Ende das LF oder CR LF mit Notepad++ weg, und Du wirst sehen, die Textdatei hat am Ende keinen definierten Zustand. Leider sagt Dein Link am Ende nur was darüber, in welchem Format die Dateien gespeichert werden können. Es gibt aber keine Einstellung, der man sagen kann, wie das EOF direkt aussieht.

Das ist ja als Vielschreiber unter Unix und Windows das verwirrende. Mache ich im vi am Ende noch ein Return, habe ich 2x 0a in der Datei stehen, und in Windows mal 0d0a oder 0a (Unix-Format). Das ist bei diversen Programmen und Batchbefehlen sehr wohl kritisch, wenn am Ende 2x 0a drinsteht, das heißt an sich leere Zeile ohne Inhalt, und dann laden u.U. Murksdaten in eine Datenbank, wenn man das nicht separat abfängt.
espiritup schrieb:
  • Interessant wäre, wie sich andere verbreteitete Editoren unter Linux verhalten. Nano zum Beispiel. Fügt der auch eine Leerzeile ein beim Speichern?
Der macht es ebenso korrekt. Wenn ich mich dunkel an meine C-Zeiten erinnere, meine ich, daß die entsprechenden Schreibfunktionen das sogar selbst so setzen, sobald man zeilenweise schreibt. Java macht es definitiv so. Nur wenn man byteweise aus einem Puffer schreibst, muß man den Zeilentrenner selbst erzeugen.
 
Zuletzt bearbeitet:
Ketzerische Frage:
Wenn ich eine «Zeile» mit [Enter] beende erwarte ich je nach dem \n\r oder \n. OK.
Woher aber soll ein Editor prinzipiell wissen wann ich das Zeilenende wünsche ohne es klar anzugeben?

OK, gibt es eine 2. oder 3. Zeile muss die jeweils letzte irgendeinen Terminus haben. Bekommen haben, von mir.
Ich könnte aber eine Datei mit 1 Zeile tippen und ohne [Enter] speichern. Woher soll oder muss da ein Terminus aufkreuzen?!

Offenbar ist es wortwörtlich Einstellungssache mit was meine Zeile beendet wird. Da wird man generell nichts machen können.

CN8
 
  • Gefällt mir
Reaktionen: Micha45 und blöderidiot
PHuV schrieb:
und dann laden u.U. Murksdaten in eine Datenbank, wenn man das nicht separat abfängt.
Das Argument zieht nicht. Lade ich Daten, muss ich diese immer prüfen, immer. Selbst wenn ich davon ausgehen könnte, dass die Daten nicht vorsätzlich manipuliert wurden, können sie durch andere Mechanismen beschädigt worden sein.

PHuV schrieb:
Genau das ist ja der Kniff, laß man am Ende das LF oder CR LF mit Notepad++ weg, und Du wirst sehen, die Textdatei hat am Ende keinen definierten Zustand.
Den undefinierten Zustand habe ich aber nur, wenn ich vorher definiert habe, das jedes Zeilenende mit einem wiederum definierten Zeilenendezeichen zu markieren ist. Da sind wir wieder beim Thema Syntax.

Eine JSON-Datei braucht kein "Newline", sondern wahrscheinlich eher eine schließende geschweifte Klammer, aber auch das nicht unbedingt (ein Newline tut hier auch nicht weh, das ist mir klar). Schreibe ich einen Text, braucht es auch kein "Newline" am Ende einer Zeile, sondern ein Satzzeichen. Davon gibt es nur dummerweise verschiedene, welches sollte der Editor nun also setzen? Einen Punkt, ein Fragezeichen, ein Ausrufungszeichen? Und woher soll der Editor überhaupt wissen, dass ich gerade einen Text und keine Konfigdatei schreibe? Vielleicht schreibe ich auch einen Text über das JSON Format!? Und vielleicht will ich ja gezielt einen Fehler einbauen, um etwas zu testen!?

Ich freue mich bei einem Editor immer über umfangreiche Möglichkeiten, einen Syntaxcheck durchführen zu können. Und ich finde auch Hinweise zu möglichen Lösungen gefundener Probleme schön. Aber bitte nicht automatisch und auf keinen Fall, ohne mich darüber zu informieren! Das ist zumindest meine Sicht der Dinge :)
 
Zuletzt bearbeitet: (Typo)
  • Gefällt mir
Reaktionen: Ebrithil und blöderidiot
Hallo @PHuV,

ich denke, Du hast Dich da in etwas verrannt, was es nicht gibt. Zeilenende am Dateiende ist reine Konvention. Kann man machen, muß man nicht. Wenn eine Software "zeilenweise" ausgibt, wird sie auch die letzte Zeile mit dem [CR]LF ausgeben. Aber muss nicht. Das steht nirgends ;)

Wenn ich in C eine Datei zeilenweise lese, dann bekomme ich die letzte Zeile entweder mit oder ohne angehängtes [CR]LF. Das bedeutet m. E. nach gar nichts. Ich würde nie auf die Idee kommen, mich auf sowas zu verlassen.

Und ein EOF gibt es gar nicht. Das ist auch eine Konvention, ein "Zustand" des Leseprozesses, wenn nichts mehr gelesen werden kann. Meistens (C) als int(-1) repräsentiert. Ich glaube, ich habe sogar mal vor 20 Jahren eine Art "EOF" als Zeichen (Ctrl-Z) in einer Datei gesehen, dass muss eine Wordstar-Datei von 1990 oder so gewesen sein ;)
 
Zuletzt bearbeitet:
Ich hätte hier einige Gegenargumente
  1. Bei Textdateien sollte immer automatisch eine Terminierung per EOF und Zeilentrenner erfolgen. Ich würde es ja noch verstehen, wenn die Dateiendung nicht txt ist. Wie gesagt, ansonsten haben wir das Problem, daß die meisten Programme das Dateiende nicht erkennen können.
  2. Mir ist aktuell kein Tool oder Programmiersprache im Batchbereich bekannt, siehe diverse Shells, Perl, Windows Batch, cmd und Powershell, was bei einer Umlenkung per Pipe, sprich >, keinen Zeilentrenner in die generierte Ausgabedatei erzeugt. Ebenso erzeugen alle mir bekannten Programmiersprachen im ACSII-Modus einen Zeilentrenner.

blöderidiot schrieb:
ich denke, Du hast Dich da in etwas verrannt, was es nicht gibt. Zeilenende am Dateiende ist reine Konvention. Kann man machen, muß man nicht. Wenn eine Software "zeilenweise" ausgibt, wird sie auch die letzte Zeile mit dem [CR]LF ausgeben. Aber muss nicht. Das steht nirgends ;)
Sagen wir es mal so, wenn Du all die Programmierhandbücher siehst, Anfang 80er bis heute, kann man sehr wohl davon ausgehen, daß es hier einen allgemeinen Konsens gibt.
blöderidiot schrieb:
Wenn ich in C eine Datei zeilenweise lese, dann bekomme ich die letzte Zeile entweder mit oder ohne angehängtes [CR]LF. Das bedeutet m. E. nach gar nichts. Ich würde nie auf die Idee kommen, mich auf sowas zu verlassen.
Aus Erfahrung und nach meiner Erinnerung nach gab es aber sehr wohl in C Funktionen, die dann hier Probleme machten, und die letzte Zeile nicht mehr korrekt eingelesen haben.
blöderidiot schrieb:
Und ein EOF gibt es gar nicht. Das ist auch eine Konvention, ein "Zustand" des Leseprozesses, wenn nichts mehr gelesen werden kann. Meistens (C) als int(-1) repräsentiert. Ich glaube, ich habe sogar mal vor 20 Jahren eine Art "EOF" als Zeichen (Ctrl-Z) in einer Datei gesehen, dass muss eine Wordstar-Datei von 1990 oder so gewesen sein ;)
Ist bei DOS auch so, https://de.wikipedia.org/wiki/End_of_File
 
Zuletzt bearbeitet:
Wir drehen uns im Kreis. Erwartet ein Programm eine gewisse Syntax, um Daten vollständig und korrekt einlesen zu können, dann muss die Syntax passen. Diese Syntax muss definiert sein. An diesem Punkt sind wir uns wohl alle einig.

Und natürlich gibt es Programme/Funktionen/etc. die beim zeilenweise Einlesen aus einer Textdatei ein "Newline" als Zeilentrenner erwarten. Genauso, wie es Tools gibt, die eine schließende geschweifte Klammer oder ein Schlüsselwort, wie z.B. "END", erwarten. Damit ist an der Stelle die Syntax vorgegeben. Will ich solche Daten erzeugen, muss ich jede Zeile mit dem definierten Zeilenendezeichen beenden. Ich kenne genauso Tools (und das dürften tatsächlich die meisten sein), die eine Zeile am Zeilenendezeichen oder durch das Ende der Datei erkennen. Letzteres muss durch die Betriebssystemfunktionen korrekt erkannt und gemeldet werden.

PHuV schrieb:
ansonsten haben wir das Problem, daß die meisten Programme das Dateiende nicht erkennen können
Das halte ich für eine extrem gewagte These. Meine im Einsatz befindlichen Programme, wie nginx, haproxy, docker, openssl, ansible, elasticsearch, postgresql, usw. lesen wunderbar Plaintextdateien (z.B. ihre Konfigurationen) ohne abschließendes "Newline" oder andere spezielle "Dateiende"-Markierungen in der jeweiligen Datei. Deren Syntax ist entsprechend definiert. Die merken irgendwann: "huch, die Datei ist zuende, na dann versuche ich das Zeug mal zu verdauen". Jetzt fangen wir aber an, zwei völlig unterschiedliche Dinge zu vermischen: Zeilenende (bei zeilenorientierten Daten) und Dateiende. Letzteres wird durch die Systemfunktionen zum Lesen von Dateien gemeldet (Anfang und Ende einer Datei ist in den Metadaten des Dateisystem vermerkt bzw. aus den Metadaten ersichtlich) und kann ein Zeilenende implizieren. Das ist dann aber wieder die Aufgabe der Programmlogik.
 
  • Gefällt mir
Reaktionen: DubZ und BlackMark
Zurück
Oben