Różnica między „\ n” a „\ r \ n”

99

Tak, zdaję sobie sprawę, że '\n'pisze do nowej linii w systemie UNIX, podczas gdy dla Windows jest sekwencja dwóch znaków: '\r\n'. Wszystko to jest bardzo ładne w teorii, ale moje pytanie brzmi: dlaczego ? Dlaczego znak powrotu karetki jest dodatkowy w systemie Windows? Jeśli UNIX może to zrobić, \ndlaczego zajmuje to Windowsowi dwa znaki?

Czytam książkę Davida Beazleya w Pythonie, a on mówi:

Na przykład w systemie Windows napisanie znaku „\ n” faktycznie wyprowadza dwuznakową sekwencję „\ r \ n” (a podczas odczytywania pliku ponownie „\ r \ n” jest tłumaczone z powrotem na pojedynczy „\ n” postać).

Dlaczego dodatkowy wysiłek?

Będę szczery. Różnicę znam od dawna, ale nigdy nie zadałem sobie trudu, by zapytać DLACZEGO. Mam nadzieję, że odpowiedź jest dziś.

Dziękuję za Twój czas.

sukhbir
źródło
5
Należy również zauważyć, że Windows nie jest jedynym, który używa \r\n. Jest również używany przez większość tekstowych protokołów internetowych (np. SMTP, HTTP itp.) Z zasadniczo tego samego powodu, co Windows (tj. Historia).
Dean Harding,
3
Ponadto w Javie i przy użyciu ciągów formatowania (np. System.out.printf()Lub String.format()) upewnij się, że używasz %njako CRLF do celów zgodności z systemem operacyjnym. \njest przestarzałe.
Gary Rowe,
Widziałem \n\rkilka razy. (Myślę, że to było coś z NetWare.)
grawity
1
Istnieje bardzo niewiele programów Windows, które faktycznie wymagają CRLF. CRLF może być domyślny, ale prawie wszystko automatycznie wykryje i użyje LF w porządku. Mam wszystkie moje edytory tekstu w systemie Windows skonfigurowane do używania plików LF dla wszystkich nowych plików, i to naprawdę nie jest problem.
Kevin

Odpowiedzi:

124

Kompatybilność wsteczna.

Windows jest wstecznie kompatybilny z MS-DOS (agresywnie, a nawet), a MS-DOS zastosował konwencję CR-LF, ponieważ MS-DOS był kompatybilny z CP / M-80 (nieco przypadkiem), który zastosował konwencję CR-LF, ponieważ to to jak prowadziłeś drukarkę (ponieważ drukarki były pierwotnie sterowanymi komputerowo maszynami do pisania).

Drukarki mają osobne polecenie przesunięcia papieru o jeden wiersz w górę do nowego wiersza oraz osobne polecenie powrotu karetki (tam, gdzie papier został zamontowany) z powrotem na lewy margines.

Dlatego. I tak, jest to irytujące, ale jest to część pakietu, który pozwolił MS-DOS wygrać z CP / M, a Windows 95 wygrać z wszystkimi innymi GUI na DOS, a Windows XP przejąć kontrolę z Windows 98.

(Uwaga: Nowoczesne drukarki laserowe nadal mają te polecenia, ponieważ one również są wstecznie kompatybilne z wcześniejszymi drukarkami - w szczególności HP robi to dobrze)

Dla osób niezaznajomionych z maszynami do pisania, oto film pokazujący, jak piszono na maszynie: http://www.youtube.com/watch?v=LJvGiU_UyEQ . Zauważ, że papier jest najpierw przesuwany w górę, a następnie karetka jest zwracana, nawet jeśli dzieje się to w prostym ruchu. Ding powiadomił maszynistkę, że koniec się zbliża i przygotowuje się na to.


źródło
3
Jak Unix ze swoim \ n pracował tylko z drukarką z dawnych czasów? Zakładam, że mieli konsole Unix podłączone do drukarek typu maszyna do pisania?
Senthil Kumaran,
3
@Senthil, w Uniksie znak nowej linii jest konwertowany przez sterownik końcowy. To tylko inna decyzja projektowa.
2
@ Dokładnie @Senthil w Unixowych drukarkach i terminalach są abstrakcyjne w systemie operacyjnym, a ich opis określa, które sekwencje bajtów są generowane dla urządzenia. CP / M nie miał takiej abstrakcji, pozostawiając wszystko działającemu programowi - jest to najprawdopodobniej dlatego, że nie było to potrzebne wszystkim programom, więc posiadanie go w rezydentnym systemie operacyjnym zabrałoby cenną pamięć programom, które jej nie potrzebują. Pamiętaj, że CP / M został zaprojektowany dla systemu 16 kilobajtów .
1
„Tak więc główną cechą konstrukcyjną prawdopodobnie najbardziej zaawansowanego systemu transportu na świecie była pierwotnie szerokość konia.” Tak samo jest z oprogramowaniem. astrodigital.org/space/stshorse.html
Ryan Michela
1
@Ryan, miejska legenda. Debunked at snopes.com/history/american/gauge.htm
20

O ile mi wiadomo, nawiązuje do czasów maszyn do pisania.

\r to powrót karetki, czyli ruch, w którym piszesz na stronie z powrotem w lewo (lub w prawo, jeśli taka jest Twoja kultura)

\n to nowa linia, która przesuwa papier w górę o linię.

Wykonanie tylko jednego z nich na maszynie do pisania postawi cię w niewłaściwym miejscu, aby rozpocząć pisanie nowego wiersza tekstu.

Kiedy pojawiły się komputery, pewnie niektórzy ludzie zachowali stary model, ale inni zdali sobie sprawę, że nie jest to konieczne i zapakowali całą nową linię jako jedną postać.

Matt Ellen
źródło
7
Dlaczego więc system Windows nadal się tego trzyma?
sukhbir
8
Kompatybilność wsteczna. Wyobraź sobie, ile dokumentów tekstowych pękłoby, gdyby się zmieniły
Matt Ellen
4
Ściśle mówiąc, „nieparzystą” jest tutaj uniksoid „używaj tylko nowej linii”, początkowo zrobiony (sądzę), aby utrzymać liczbę przechowywanych znaków na niskim poziomie (tłumaczenie na CR LF odbywa się w sterowniku terminalu, jest to flaga „onlcr” która kontroluje produkcję
Vatine
3
Windows miał poprzednika o nazwie DOS, który miał to samo zakończenie linii. System Windows zachował zgodność. DOS miał swoich poprzedników, mianowicie CP / M. Wykorzystano również CRLF. DOS zachował kompatybilność. Na rozwój CP / M miał wpływ DECS TOPS. I możesz zgadnąć, jakiego rodzaju linii użyli. :-) Zgodność wyjaśnia wiele.
Mnementh,
5
OK, ale dlaczego Notatnik nadal nie rozpoznaje zakończeń linii „\ n”?
dan04
8

Nie wiem, czy jest to powszechna wiedza, ale należy zauważyć, że CR jest nadal rozumiany przez współczesne emulatory terminali:

$ printf "hey world\rsup\n"
sup world

Jest to przydatne w przypadku wskaźników postępu, np

for i in {1..100}
do
    printf "\rLoading... %d%%" $i
    sleep 0.01
done
echo
Daniel Lubarov
źródło
1
W starych drukarkach liniowych IBM (np. 1403) konwencja traktowała pierwszy znak bufora linii jako znak kontroli karetki. Puste oznaczało przejście o jedną linię i wydrukowanie. Plus miał na celu pominięcie odstępów i został użyty np. Do podkreślenia. Zero oznacza podwójną spację, a minus potrójną spację. „1” odstępu u góry następnej strony i inne cyfry przesuwane do pozycji pionowych zdefiniowanych przez użytkownika (używane do wypełniania wstępnie wydrukowanych formularzy).
George
7

Historycznie przesunięcie linii oznaczało, że wałek - wałek, na którym piszesz - obrócił jedną linię, powodując pojawienie się tekstu w następnej linii ... ale w następnej kolumnie.

Zwrot karetki oznacza „zwróć bit, za pomocą którego piszesz na początku wiersza”.

Windows używa CR + LF, ponieważ zrobił to MS-DOS, ponieważ zrobił to CP / M, ponieważ miało to sens dla linii szeregowych.

Unix skopiował swoją konwencję, ponieważ zrobił to Multics.

Podejrzewam, że jeśli wykopiesz wystarczająco daleko, znajdziesz polityczne spory między realizatorami!

(Pominąłeś dodatkowy zabawny bit, w którym konwencja Mac jest (lub kiedyś była), aby po prostu używać CR do oddzielania linii. A teraz Unicode ma również swój własny separator linii, U + 2028!)

Frank Shearar
źródło
Łał! nie wiedziałem o Macu ...
Michael K
Nie jestem pewien, czy spotkałbyś się z nieporozumieniem politycznym. Możliwe jest również, że znajdziesz osoby robiące podobne rzeczy niezależnie.
David Thornley,
1
Kiedy zaangażowane są różne organy normalizacyjne? Byłbym zaskoczony, że nie znalazłem powodów politycznych!
Frank Shearar,
6

Historia znaku nowej linii (Wikipedia):

ASCII został opracowany jednocześnie przez ISO i ASA, poprzednią organizację ANSI. W latach 1963–1968 projekty norm ISO wspierały użycie CR + LF lub samego LF jako nowej linii, podczas gdy projekty ASA wspierały tylko CR + LF.

Sekwencja CR + LF była powszechnie stosowana w wielu wczesnych systemach komputerowych, które przyjęły maszyny typu teletechnicznego, zwykle ASR33, jako urządzenie konsoli, ponieważ sekwencja ta była wymagana do umieszczenia tych drukarek na początku nowej linii. W tych systemach tekst był często rutynowo komponowany w celu zapewnienia zgodności z tymi drukarkami, ponieważ koncepcja sterowników urządzeń ukrywających takie szczegóły sprzętu przed aplikacją nie była jeszcze dobrze opracowana; aplikacje musiały rozmawiać bezpośrednio z maszyną teletechniczną i przestrzegać jej konwencji.

Rozdzielenie tych dwóch funkcji ukrywało fakt, że głowica drukująca nie mogła wrócić od skrajnej prawej do początku następnego wiersza w czasie jednego znaku. Dlatego sekwencja była zawsze wysyłana najpierw z CR. W rzeczywistości często trzeba było wysyłać dodatkowe znaki (obce CR lub NUL, które są ignorowane), aby dać głowicy drukującej czas na przejście do lewego marginesu.

Nawet po zastąpieniu teletypów terminalami komputerowymi o większej szybkości transmisji wiele systemów operacyjnych nadal obsługiwało automatyczne wysyłanie tych znaków wypełniania, aby zapewnić zgodność z tańszymi terminalami, które wymagały wielokrotnego przewijania ekranu.

MS-DOS (1981) przyjął CR / L CR + LF; Zastosowanie CR / LF przez CP / M miało sens w używaniu terminali komputerowych poprzez linie szeregowe. Konwencję tę odziedziczył późniejszy system operacyjny Microsoft Windows.

System operacyjny Multics rozpoczął opracowywanie w 1964 roku i jako jedyny zastosował sam LF. Unix podążył za praktyką Multics, a później systemy podążyły za Unixem.

Craige
źródło
Na starym terminalu drukarka-klawiatura IBM 2741 komponentem drukarki była maszyna do pisania typu odbijająca kulka IBM Selectric. Zmiana na wielkie litery spowodowała obrót piłki, co zajęło więcej czasu. W kodzie znaków EBCDIC wielkie litery miały 1-bit w pozycji 6. Zatem puste miejsce EBCDIC (0x40) było wielkie! Jeśli drukujesz długi dokument (np. Rozprawę), możesz znacznie przyspieszyć wydruk, tłumacząc puste znaki między małymi słowami na NUL lub małe litery (używali innego znaku, IL jeśli pamięć służy, aby wprowadzić niezbędne opóźnienia, np. , podczas powrotu lub tabulacji).
George
5

Co to jest, gdy ludzie pytają „dlaczego Unix potrafi, \na nie Windows”? To takie dziwne pytanie.

  1. System operacyjny prawie nie ma z tym nic wspólnego. To bardziej kwestia tego, jak aplikacje, biblioteki, protokoły i formaty plików radzą sobie z różnymi rzeczami. Poza przypadkami, gdy system operacyjny odczytuje / zapisuje konfigurację tekstową lub polecenia wiersza poleceń, nie ma sensu obwiniać systemu operacyjnego.
  2. Większość aplikacji Windows potrafi czytać zarówno \ni \r\ndobrze. Produkują również \r\n, aby wszyscy byli szczęśliwi. Program nie tylko „wykonuje” jedno \nlub drugie \r\n- akceptuje jedno, drugie lub oba i wysyła jeden, drugi lub oba.
  3. Jako programista naprawdę nigdy nie powinno ci to przeszkadzać. Praktycznie każdy język / platforma ma możliwości napisania poprawnej linii końcowej i najsolidniejszego czytania. Jedyny raz, kiedy miałem do czynienia z tym problemem, to kiedy napisałem serwer HTTP - i to dlatego, że pewna przeglądarka (wskazówka: następna najpopularniejsza przeglądarka po IE) działała \nzamiast poprawnej \r\n .
  4. O wiele bardziej trafnym pytaniem jest, dlaczego tak wiele współczesnych aplikacji uniksowych wypisuje się w \npełni wiedząc, że istnieją protokoły i programy, które tego nie lubią?
Rei Miyasaka
źródło
3
Kolejne istotne pytanie: skoro wiele protokołów zostało opracowanych głównie na systemach uniksowych, dlaczego nie używali „\ n”?
David Thornley,
@DavidThornley Ponieważ \ r \ n jest bardziej prawdopodobne, że będzie działać na różnych platformach (\ r dla starszych komputerów Mac, \ r \ n dla Windows i \ n dla * nix).
Podstawowy
4

Powodem, dla którego konwencje obowiązują w różnych systemach (\ n w systemach typu Unix, \ r \ n w systemie Windows itp.) Jest to, że po wybraniu konwencji NIE MOŻNA jej zmienić bez niszczenia wielu plików ludzi. I to na ogół marszczy brwi.

Systemy typu uniksowego zostały opracowane (bardzo wcześnie) przy użyciu różnych modeli teletypu, i w pewnym momencie ktoś zdecydował, że sprzęt powinien powrócić, gdy przesunie linię.

Windows pochodzi z DOS, więc dla Windows pytanie brzmi: Dlaczego DOS użył tej sekwencji cr / lf? Zgaduję, że ma to coś wspólnego z CP / M, gdzie DOS ma swoje korzenie. Ponownie, niektóre modele telegrafu mogły odegrać pewną rolę.

Michael Kohne
źródło
Hmm interesujące.
sukhbir
1
Dlaczego system Windows nie obsługuje linii kończących się na \n, ale nadal go używa \r\n? Gdyby to zrobili, zaczynając od systemu Windows XP, mogliby teraz zacząć zapisywać pliki za pomocą \nzamiast \r\n.
DisgruntledGoat
1
Windows nie ma z tym nic wspólnego. To jest decyzja aplikacji, a większość aplikacji będzie czytać zarówno „\ n”, jak i „\ r \ n” i pisać „\ r \ n” - więc wszyscy są zadowoleni.
Rei Miyasaka,
2

Oto odpowiedź z najlepszego źródła - Microsoft. Dlaczego terminator linii CR + LF?

Protokół ten pochodzi z czasów pisarzy teletypowych. CR oznacza „powrót karetki” - znak kontrolny CR zwrócił głowicę drukującą („karetkę”) do kolumny 0 bez przesuwania papieru. LF oznacza „podawanie linii” - znak kontrolny LF przesunął papier o jedną linię bez poruszania głowicą drukującą. Więc jeśli chcesz przywrócić głowicę drukującą do kolumny zero (gotowy do wydrukowania następnego wiersza) i przesunąć papier (aby drukował na świeżym papierze), potrzebujesz zarówno CR, jak i LF.

Jeśli przejdziesz do różnych dokumentów protokołu internetowego, takich jak RFC 0821 (SMTP), RFC 1939 (POP), RFC 2060 (IMAP) lub RFC 2616 (HTTP), zobaczysz, że wszystkie one określają CR + LF jako sekwencja zakończenia linii. Tak więc prawdziwe pytanie nie brzmi: „Dlaczego CP / M, MS-DOS i Win32 używają CR + LF jako terminatora linii?” ale raczej „Dlaczego inni ludzie zdecydowali się odbiegać od tych standardowych dokumentów i użyć innego terminatora linii?”

Unix przyjął zwykły LF jako sekwencję zakończenia linii. Jeśli spojrzysz na opcje stty, zobaczysz, że opcja onlcr określa, czy LF należy zmienić na CR + LF. Jeśli pomylisz się z tym ustawieniem, otrzymasz tekst schodkowy, gdzie

each
    line
        begins

gdzie poprzednia linia została przerwana. Zatem nawet unix, gdy jest pozostawiony w trybie surowym, wymaga CR + LF do zakończenia linii. Ukryta CR przed LF jest wynalazkiem uniksowym, prawdopodobnie jako ekonomia, ponieważ oszczędza jeden bajt na linię.

Unikalne pochodzenie języka C przenosiło tę konwencję do standardu języka C, który wymaga tylko „\ n” (który koduje LF) do zakończenia linii, nakładając obciążenie na biblioteki wykonawcze na konwersję danych surowego pliku na linie logiczne.

Język C wprowadził również termin „nowa linia”, aby wyrazić koncepcję „ogólnego terminatora linii”. Powiedziano mi, że komitet ASCII zmienił nazwę znaku 0x0A na „newline” około 1996 r., Więc poziom zamieszania został podniesiony jeszcze wyżej.

Ondra Žižka
źródło