Перенос строки в linux и windows

Обновлено: 02.07.2024

Я хотел бы знать разницу (с примерами, если это возможно) между типами разрыва строки CR LF (Windows), LF (Unix) и CR (Macintosh).

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

больше информации, как всегда, на Википедия.

CR и LF являются управляющими символами, соответственно закодированными 0x0D (13 десятичных знаков) и 0x0A (10 десятичное).

Они используются для обозначения разрыва строки в текстовом файле. Как вы указали, Windows использует два символа последовательности CR LF; Unix использует только LF, а старый MacOS (pre-OSX MacIntosh) использовал CR.

апокрифическая историческая перспектива:

как отметил Петр, CR = Возврат Каретки и LF = Строки, два выражения имеют свои корни в старых пишущих машинках / TTY. LF переместил бумагу вверх (но сохранил горизонтальное положение идентичным), а CR вернул "каретку" так, чтобы следующий введенный символ был в крайнем левом положении на бумаге (но на той же строке). CR+LF делал и то, и другое, то есть готовился ввести новую строку. С течением времени физическая семантика кодов была неприменима, а поскольку память и дискетное пространство были в цене, некоторые ОС дизайнеры решили использовать только одного из персонажей, они просто не очень хорошо общались друг с другом ;-)

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

это хорошее резюме, которое я нашел:

символ возврата каретки (CR) ( 0x0D , \r ) перемещает курсор в начало строки, не перейти к следующей строке. Этот символ используется в качестве нового символа строки в Commodore и ранних операционных системах Macintosh (OS-9 и более ранних).

символ подачи строки (LF) ( 0x0A , \n ) перемещает курсор к следующей строке, не возвращаясь к началу линии. Этот символ используется как новый символ строки в системах на базе UNIX (Linux, Mac OSX и т. д.)

конец строки (EOL) последовательности ( 0x0D 0x0A , \r\n ) на самом деле два символа ASCII, комбинация символов CR и LF. Он перемещает курсор как вниз к следующей строке, так и к началу этой строки. Этот символ используется в качестве нового символа строки в большинстве других операционных систем, отличных от Unix, включая Microsoft Windows, Symbian OS и другие.

поскольку нет ответа, заявляющего только это, кратко резюмировал:

Возврат Каретки (Mac pre-OSX)

Строки (Linux, MAC OSX)

возврат каретки и подача линии (Windows)

  • CRLF
  • \r\n
  • ASCII код 13, а затем ASCII код 10

Если вы видите код ASCII в странном формате, это просто число 13 и 10 в другом радиксе/базе, обычно база 8 (восьмеричная) или база 16 (шестнадцатеричная).

LF - ASCII код 10.

теоретически CR возвращает курсор в первую позицию (слева). LF подает одну строку, перемещая курсор на одну строку вниз. Вот как в старые времена вы управляли принтерами и текстовыми мониторами. Эти символы обычно используются для обозначения конца строк в текстовых файлах. В разных операционных системах используются разные соглашения. Как вы указали, Windows использует комбинацию CR/LF, а pre-OSX Mac использует только CR и так далее.

системы на основе ASCII или a совместимый набор символов, использовать если (Линия подачи, 0x0A, 10 в десятичном) или CR (возврат каретки, 0x0D, 13 в десятичном) индивидуально, или CR следовать LF (CR+LF, 0x0D 0x0A); Эти символы основаны на командах принтера: подача строки указано, что одна строка бумага должна подаваться из принтера, а каретка-возвращаться указано, что принтер перевозка должна возвратиться к началу течения линия.

печальное состояние "разделителей записей" или "линейных Терминаторов" является наследием темных веков вычислений.

но когда-то это было не совсем так. Применения встроенные характеры управления и прибор-специфическая обработка. Мозг-мертвые системы, которые требовали и CR, и LF просто не имели абстракции для разделителей записей или линейных Терминаторов. CR был необходим для того, чтобы заставить телетайп или видеодисплей вернуться в столбец один, а LF (сегодня, NL, тот же код) был необходим, чтобы заставить его перейти к следующей строке. Я думаю, идея сделать что-то другое, кроме сброса необработанных данных на устройство, была слишком сложной.

Unix и Mac фактически указали абстрагирование для конца линии, представьте себе это. К сожалению, они уточнили разные. (Unix, кхм, пришел первым.) И, естественно, они использовали код управления, который уже был "близок" к S. O. P.

поскольку почти все наше операционное программное обеспечение сегодня является потомком Unix, Mac или MS operating SW, мы застряли с линией, заканчивающейся путаницей.

NL, полученный из EBCDIC NL = x '15', который логически сравнивался бы с CRLF x'odoa ascii. это становится очевидным, когда physcally перемещение данных с мейнфреймов на сч. Coloquially (как только тайные люди используют ebcdic) NL был приравнен к CR или LF или CRLF

Notepad в windows 10 начал понимать юниксовый перевод строки, а не только формат Windows.

С проблемой «каши» вместо удобочитаемого текста десятилетиями сталкивались те, кто пытался открыть в среде Windows текстовые документы, подготовленные на других операционных системах. Теперь же всё в одночасье изменяется. И это изменение столь же мало, сколь и эпично по своим практическим результатам и идеологическим последствиям. Microsoft вновь пытается играть в кросс-интеграцию и поддержку открытых стандартов.

Долгие годы Windows Блокнот мог нормально отображать только те текстовые документы, которые содержали символы начала новой строки в формате Windows End of Line (EOL) — «возврат каретки» (CR) и «подача на строку» (LF). На деле это приводило к тому, что Notepad не смог правильно отобразить содержимое текстовых файлов, созданных в Unix, Linux и macOS, где в качестве признака конца строки использовался только символ LF.

Например, вот скриншот Notepad, пытающегося отобразить содержимое текстового файла Linux .bashrc, который содержит только символы Unix LF EOL:

image

А вот скриншот недавно обновленного «Блокнота», отображающего содержимое того же самого файла UNIX / Linux .bashrc, но с правильными переносами:

image


Обратите внимание, что строка состояния указывает обнаруженный формат EOL текущего открытого файла.

Так же для гибкого управления новой возможностью в разделе реестра [HKEY_CURRENT_USER\Software\Microsoft\Notepad] вводятся два дополнительных ключа:

image

По накалу страстей спор о способе начала новой строки в электронных документах сравним со спором о пробелах и табуляциях в исходных текстах программ. У этого противостояния «за строку» было много причин, как лежащих в области древних стандартов и традиций, так и берущих свои корни в особенностях конструкции печатных машин и телетайпов. Не меньшую роль сыграло и стремление одних программистов буквально выполнять (интерпретировать) команды и управляющие символы, а других — следовать здравому смыслу.

Что мы можем узнать о проблеме из Википедии

Исторически на механических пишущих машинках был рычаг, который возвращал каретку к левому краю страницы и прокручивал вал, подвигая бумагу вверх на строку. На телетайпах и более поздних алфавитно-цифровых печатающих устройствах (АЦПУ) вместо каретки была головка, в лазерных принтерах она перестала быть материальной, но в термине возврат каретки всё это продолжали называть кареткой, чтобы его не менять. На телетайпах возврат каретки и подачу строки разделили, откуда традиция представления перевода строки как CR+LF перешла и к текстовым файлам.

Системы, основанные на ASCII или совместимом наборе символов, используют или LF (перевод строки, 0x0A), или CR (возврат каретки, 0x0D) по отдельности, или последовательность CR+LF. Эти названия основаны на командах принтера: перевод строки означает, что одна строка на бумаге должна быть перенесена при печати, а возврат каретки означает, что каретка печатающего устройства должна вернуться к началу текущей строки.

  • LF (U+000A): англ. line feed — подача строки <ПС>;
  • CR (U+000D): англ. carriage return — возврат каретки <ВК>;
  • NEL (U+0085): англ. next line — переход на следующую строку;
  • LS (U+2028): англ. line separator — разделитель строк;
  • PS (U+2029): англ. paragraph separator — разделитель абзацев.

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

Юникод старается примирить эту разницу, уравнивая CR, LF и CR+LF, однако вступает в противоречие с наследуемым им ASCII при трактовке последовательности LF+CR, не предварённой CR: согласно ASCII это один перевод строки, а согласно Юникоду — два.

то в Windows в файл будет записано CR+LF, а в Linux будет записано LF.
Как задать в тексте программы, чтоб \n в строках интерпретировался при выводе в файл одинаково (либо CR+LF, либо LF по выбору) ?

А то получается что файлы в Windows и Linux побайтно не совпадают.

Неа. В Винде опять получишь CR+LF+CR

Попробуй юзать fstream, там, возможно этого не будет.

futures
> Если написать на С++
> fprintf(fp, "\n");
Это не на С++, это на Си.
А на С++

При желании можно последовательность 0x0d,0x0a заменить функцией или макросом.

std::endl не поможет случаем?

Какой-то ужас.
Достаточно просто указать в fopen режим "wb".

Ответ уже дали:
flatz> Достаточно просто указать в fopen режим "wb".

>> std::ofstream fp;
>> fp.open("file.txt");
>> fp << "Hello futures" << 0x0d << 0x0a; // если использовать std::endl - то получится то же самое, что и с \n
>> fp.close();
я понимаю, что можно просто вместо \n прописать свою константу и ее уже выводить как один или два символа, но в таком случае:
1) теряется наглядность, если в строке много чего выводится, то намного удобнее чтоб там был просто вывод \n
2) уже есть куча написанного кода просто с \n, теперь придется вручную его изменять.

>> Достаточно просто указать в fopen режим "wb".
ну про бинарный режим открытия файла я понимаю, но тогда в Windows вместо \n будет записан только LF, и большинство виндовс-программ не будут его нормально открывать, что очень неудобно (ну или нужно лазить по всей программе и заменять всюду \n на \r\n).
Вообще то я склоняюсь к тому, чтоб и в Виндовс и в Линукс мне будет удобнее заменять \n на CR+LF, только вот как автоматизировать этот процесс, чтоб не менять все в тексте программы, а раз задать константу?

А может можно как-то переопределить std::endl на то, что мне нужно(либо CR+LF, либо LF по выбору )?

futures
> но тогда в Windows вместо \n будет записан только LF, и большинство
> виндовс-программ не будут его нормально открывать
Ну а \n\r туда записать конечно же по каким-то причинам уже нельзя.

futures
Ты все-таки определись, что именно тебе нужно - бинарная совместимость файлов или то, чтобы в каждой из ОС соблюдался именно ее стандарт на завершение строки.
Одновременно выполнить эти два условия совершенно невозможно.

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

futures
>>мне однозначно нужна бинарная совместимость файла

Зачем нужна бинарная совместимость, если файл будет редактироваться ручками ?

futures
> Как задать в тексте программы, чтоб \n в строках интерпретировался при выводе в
> файл одинаково
Поставить флаг, что файл бинарный «fopen(". ", "wb")». Это выключит любую самодеятельность.

> большинство виндовс-программ не будут его нормально открывать
Кроме блокнота таких не замечено.

> только вот как автоматизировать этот процесс, чтоб не менять все в тексте
> программы, а раз задать константу?
Заменить \n на "NEW_LINE"(с кавычками) и соответственно объявить макрос.

Читайте также: