Разница между '\ n' и '\ r \ n'

99

Да да, я знаю , что '\n'пишет перевод строки в UNIX в то время как для Windows , существует последовательность два символа: '\r\n'. Все это очень хорошо в теории, но мой вопрос почему ? Почему символ возврата каретки является дополнительным в Windows? Если UNIX может это сделать, \nпочему для этого требуется Windows два символа?

Я читаю книгу Дэвида Бизли «Питон», и он говорит:

Например, в Windows при записи символа '\ n' фактически выводится двухсимвольная последовательность '\ r \ n' (а при чтении файла обратно, \ r \ n 'преобразуется обратно в один' \ n ' характер).

Почему дополнительные усилия?

Я буду честен Я давно знал разницу, но никогда не удосужился спросить, ПОЧЕМУ. Я надеюсь, что ответили сегодня.

Спасибо за ваше время.

Сукбер
источник
5
Следует также отметить, что Windows не единственная, которая использует \r\n. Он также используется большинством текстовых интернет-протоколов (например, SMTP, HTTP и т. Д.) По той же причине, что и Windows (т. Е. История).
Дин Хардинг
3
Кроме того, когда в Java используются строки формата (например, System.out.printf()или String.format()), убедитесь, что вы используете их в %nкачестве CRLF для совместимости с ОС. \nне рекомендуется.
Гэри Роу
Я видел \n\rнесколько раз. (Я думаю, что это было что-то из NetWare.)
grawity
1
Существует очень мало программ для Windows, которые на самом деле требуют CRLF. CRLF может быть по умолчанию, но почти все будет автоматически обнаруживаться и использовать LF просто отлично. У меня все мои текстовые редакторы в Windows настроены на использование LF для всех новых файлов, и это действительно не проблема.
Кевин

Ответы:

124

Обратная совместимость.

Windows обратно совместима с MS-DOS (даже агрессивно), и MS-DOS использовала соглашение CR-LF, потому что MS-DOS была совместима с CP / M-80 (несколько случайно), который использовал соглашение CR-LF, потому что так вы управляли принтером (потому что принтеры изначально были пишущими машинками с компьютерным управлением).

У принтеров есть отдельная команда для перемещения бумаги на одну строку вверх на новую строку и отдельная команда для возврата каретки (там, где была установлена ​​бумага) обратно на левое поле.

Вот почему. И да, это досадно, но это часть пакета, который позволил MS-DOS победить CP / M, а Windows 95 - всем остальным графическим интерфейсам поверх DOS, а Windows XP - победить. из Windows 98.

(Примечание: современные лазерные принтеры все еще имеют эти команды, потому что они также обратно совместимы с более ранними принтерами - в частности, HP делает это хорошо)

Для тех, кто не знаком с пишущими машинками, вот видео, показывающее, как печатался текст: http://www.youtube.com/watch?v=LJvGiU_UyEQ . Обратите внимание, что сначала бумага перемещается вверх, а затем возвращается каретка, даже если это происходит простым движением. Дин уведомил машинистку, что конец близок, и готовиться к нему.


источник
3
Как Unix с его \ n работал только с принтером того времени? Я предполагаю, что у них были Консоли Unix, связанные с принтерами типа пишущей машинки?
Сентил Кумаран
3
@Senthil, в Unix символ новой строки конвертируется конечным драйвером. Это просто другое дизайнерское решение.
2
@Senthil, если быть точным, в Unix принтеры и терминалы абстрагируются в операционной системе, и их описание определяет, какие последовательности байтов генерируются для устройства. У CP / M такой абстракции не было, оставляя все это запущенной программе - это, скорее всего, потому, что это было необходимо не всем программам, поэтому наличие ее в резидентной операционной системе отнимало бы драгоценную память у программ, которым она не нужна. Помните, что CP / M был разработан для системы 16 килобайт .
1
«Таким образом, главная конструктивная особенность того, что, возможно, является самой совершенной транспортной системой в мире, изначально определялась шириной задницы лошади» И так же с программным обеспечением. astrodigital.org/space/stshorse.html
Райан
1
@ Райан, городская легенда. Разоблачен
20

Насколько я знаю, это восходит к временам пишущих машинок.

\r это возврат каретки, который перемещается туда, где вы печатаете на странице обратно влево (или вправо, если это ваша культура)

\n это новая линия, которая перемещает вашу бумагу вверх по линии.

Выполнение только одной из них на пишущей машинке поставит вас в неверное место, чтобы начать писать новую строку текста.

Когда появились компьютеры, я думаю, что некоторые люди сохранили старую модель, но другие поняли, что в этом нет необходимости, и заключили полный символ новой строки в один символ.

Мэтт Эллен
источник
7
Итак, почему Windows все еще придерживается этого?
Сухбир,
8
Обратная совместимость. Представьте, сколько текстовых документов сломалось бы, если бы они изменились сейчас
Мэтт Эллен
4
Строго говоря, «чудак» здесь - это unixoid «использовать только новую строку», изначально сделанный (я верю), чтобы уменьшить количество хранимых символов (перевод в CR LF выполняется в драйвере терминала, это флаг «onlcr») который контролирует его для вывода
Vatine
3
У Windows был Предшественник по имени DOS, у которого был тот же самый конец строки. Windows сохранила совместимость. У DOS были свои предшественники, а именно CP / M. Это использовал также CRLF. DOS сохранил совместимость. На развитие CP / M оказали влияние ТОПы ОИК. И вы можете догадаться, какой lineending они использовали. :-) Совместимость многое объясняет.
Мнемент
5
Хорошо, но почему Блокнот все еще не распознает окончания строки "\ n"?
Ден04
8

Я не знаю, является ли это общеизвестным, но следует отметить, что CR все еще понимается современными эмуляторами терминала:

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

Это удобно для индикаторов прогресса, например

for i in {1..100}
do
    printf "\rLoading... %d%%" $i
    sleep 0.01
done
echo
Даниэль Любаров
источник
1
На старых строчных принтерах IBM (например, 1403) было принято считать, что первый символ строкового буфера является символом управления кареткой. Пробел предназначен для продвижения на одну строку и печати. «Плюс» означало пропускание пробелов и использовалось, например, для подчеркивания. Ноль означает двойное пространство, а минус - тройное пространство. '1' с интервалом в верхнюю часть следующей страницы, а другие цифры переводятся в заданные пользователем вертикальные позиции (используются для заполнения предварительно напечатанных форм).
Джордж
7

Исторически, перевод строки означал, что валик - ролик, на котором вы печатаете, - поворачивал одну строку, в результате чего текст появлялся на следующей строке ... но в следующем столбце.

Возврат каретки означал «вернуть бит, который вы вводите, в начало строки».

Windows использует CR + LF, потому что MS-DOS сделал, потому что CP / M сделал, потому что это имело смысл для последовательных линий.

Unix скопировал свое соглашение \ n, потому что это сделал Multics.

Я подозреваю, что если вы покопаетесь достаточно далеко назад, вы обнаружите политические разногласия между разработчиками!

(Вы пропустили дополнительный забавный бит, в котором используется соглашение Mac (или раньше) просто использовать CR для разделения строк. А теперь в Unicode также есть собственный разделитель строк, U + 2028!)

Фрэнк Шиарар
источник
Вау! не знал о Mac ...
Майкл К
Я не уверен, что вы найдете политические разногласия. Также возможно, что вы найдете людей, которые делают подобные вещи независимо.
Дэвид Торнли
1
Когда задействованы различные органы по стандартизации? Я был бы удивлен, чтобы не найти политические причины!
Фрэнк Шиарар
6

История символа новой строки (Википедия):

ASCII был разработан одновременно ISO и ASA, предшественницей ANSI. В период 1963–1968 гг. Проекты стандартов ИСО поддерживали использование только CR + LF или LF в качестве новой строки, в то время как проекты ASA поддерживали только CR + LF.

Последовательность CR + LF широко использовалась во многих ранних компьютерных системах, в которых в качестве консольного устройства использовались машины телетайпа, как правило, ASR33, поскольку эта последовательность требовалась для позиционирования этих принтеров в начале новой строки. В этих системах текст часто составлялся для совместимости с этими принтерами, поскольку концепция драйверов устройств, скрывающих такие аппаратные детали от приложения, еще не была хорошо разработана; приложения должны были напрямую общаться с телетайпом и следовать его соглашениям.

Разделение этих двух функций скрывало тот факт, что печатающая головка не могла вернуться из крайнего правого края в начало следующей строки за один символ. Вот почему последовательность всегда отправлялась сначала с CR. Фактически часто приходилось отправлять дополнительные символы (лишние символы CR или NUL, которые игнорируются), чтобы дать печатающей головке время для перехода к левому полю.

Даже после того, как телетипы были заменены компьютерными терминалами с более высокой скоростью передачи данных, многие операционные системы все еще поддерживали автоматическую отправку этих символов заполнения для совместимости с более дешевыми терминалами, которым для прокрутки дисплея требовалось несколько раз.

MS-DOS (1981) принял CR + LF CP / M; Использование CP / M CR + LF имело смысл для использования компьютерных терминалов через последовательные линии. Это соглашение было унаследовано более поздней операционной системой Microsoft Windows.

Операционная система Multics начала разработку в 1964 году и использовала только LF в качестве новой строки. Unix следовал практике Multics, а более поздние системы следовали Unix.

Craige
источник
На старом терминале принтер-клавиатура IBM 2741 компонент принтера представлял собой шариковую печатную машинку прыгающего типа IBM Selectric. Изменение в верхний регистр заставило шар вращаться, занимая дополнительное время. В коде символов EBCDIC заглавные буквы имеют 1-разрядный символ в позиции 6. Таким образом, пробел EBCDIC (0x40) был заглавным! Если вы печатали длинный документ (например, тезис), вы могли бы существенно ускорить вывод, переводя пробелы между строчными словами в NUL или строчные пробелы (они использовали другой символ, IL, если память служит, чтобы ввести необходимые задержки, например, , при возврате или вкладке).
Джордж
5

Что это за люди, спрашивающие: «Почему Unix может делать, \nа не Windows»? Это такой странный вопрос.

  1. ОС практически не имеет к этому никакого отношения. Это больше зависит от того, как приложения, библиотеки, протоколы и форматы файлов имеют дело с вещами. За исключением случаев, когда ОС читает / записывает текстовые команды конфигурации или команды командной строки, нет смысла винить ОС.
  2. Большинство приложений для Windows могут читать как хорошо, так \nи \r\nхорошо. Они также выводят, \r\nтак что все счастливы. Программа не просто «делает» \nили \r\n- она принимает одно, другое или оба, и выводит одно, другое или оба.
  3. Как программист, это должно почти никогда не беспокоить вас. Практически на каждом языке / платформе есть возможность написать правильную конечную строку и читать наиболее надежно. Единственный раз, когда мне приходилось иметь дело с этой проблемой, было, когда я писал HTTP-сервер - и это было потому, что определенный браузер (подсказка: следующий по популярности браузер после IE) работал \nвместо правильного \r\n .
  4. Гораздо более актуальный вопрос: почему так много современных приложений Unix выводят только \nполностью, зная, что есть некоторые протоколы и программы, которым это не нравится?
Рей Миясака
источник
3
Еще один уместный вопрос: поскольку многие протоколы были разработаны в первую очередь для систем Unix, почему они не использовали '\ n'?
Дэвид Торнли
@DavidThornley, потому что \ r \ n с большей вероятностью будет работать кроссплатформенно (\ r для старых macs, \ r \ n для windows и \ n для * nix).
Basic
4

Причина, по которой соглашения применяются в их различных системах (\ n в системах типа Unix, \ r \ n в Windows и т. Д.), Заключается в том, что, выбрав соглашение, вы НЕ МОЖЕТЕ изменить его, не сломав кучу файлов людей. И это вообще не одобряется.

Системы Unix-типа были разработаны (очень рано) с использованием различных моделей телетайпа, и в какой-то момент кто-то решил, что оборудование должно возвращаться, когда оно выполняло перевод строки.

Windows пришла из DOS, поэтому для Windows действительно возникает вопрос: почему DOS использовал эту последовательность cr / lf? Я предполагаю, что это как-то связано с CP / M, где DOS имеет некоторые корни. Опять же, конкретные модели телетайпа, возможно, сыграли свою роль.

Майкл Кохне
источник
Хм интересно.
Сухбир
1
Почему Windows не может обрабатывать строки, оканчивающиеся на \n, но продолжает использовать \r\nсейчас? Если бы они делали это начиная с Windows XP, они могли бы начать сохранять файлы \nвместо \r\n.
Рассерженная шлюха
1
Windows не имеет к этому никакого отношения. Это решение приложений, и большинство приложений будут читать «\ n» и «\ r \ n» и писать «\ r \ n» - так что все счастливы.
Рей Миясака
2

Вот ответ из лучшего источника - Microsoft. Почему терминатор строки CR + LF?

Этот протокол восходит ко временам телетайпов. CR означает «возврат каретки» - управляющий символ CR возвращает печатающую головку («каретка») в столбец 0 без продвижения бумаги. LF означает «перевод строки» - символ управления LF выдвигает бумагу на одну строку без перемещения печатающей головки. Поэтому, если вы хотите вернуть печатающую головку в нулевой столбец (готовый напечатать следующую строку) и продвинуть бумагу (чтобы она печаталась на свежей бумаге), вам понадобятся оба значения: CR и LF.

Если вы перейдете к различным документам интернет-протокола, таким как RFC 0821 (SMTP), RFC 1939 (POP), RFC 2060 (IMAP) или RFC 2616 (HTTP), вы увидите, что все они определяют CR + LF в качестве последовательность завершения строки. Таким образом, реальный вопрос не в том, «почему CP / M, MS-DOS и Win32 используют CR + LF в качестве ограничителя строки?» а скорее "Почему другие люди решили отличаться от этих стандартных документов и использовать какой-либо другой терминатор строки?"

Unix принял обычный LF в качестве последовательности завершения строки. Если вы посмотрите на параметры stty, то увидите, что параметр onlcr указывает, следует ли заменить LF на CR + LF. Если вы неправильно установили эту настройку, вы получите текст ступеньки, где

each
    line
        begins

где предыдущая строка остановилась. Так что даже Unix, когда он оставлен в необработанном режиме, требует CR + LF для завершения строк. Неявный CR перед LF является изобретением unix, вероятно, в качестве экономии, поскольку он экономит один байт на строку.

Родословная Unix языка C перенесла это соглашение в стандарт языка C, который требует только «\ n» (который кодирует LF) для завершения строк, что накладывает бремя на библиотеки времени выполнения для преобразования необработанных файловых данных в логические строки.

Язык C также ввел термин «новая строка», чтобы выразить понятие «терминатор родовой строки». Мне сказали, что комитет ASCII изменил имя персонажа 0x0A на «новую строку» примерно в 1996 году, поэтому уровень путаницы был поднят еще выше.

Ондра Жижка
источник