Портативный конец строки (новая линия)

Было неприятным сюрпризом, что '\n' заменен с помощью "\r\n" в Windows, я этого не знал. (Я предполагаю, что он также заменен на Mac...)

Есть ли простой способ гарантировать, что пользователи Linux, Mac и Windows могут легко обмениваться текстовыми файлами?

Простым способом я имею в виду: не записывая файл в двоичном режиме или не тестируя и не заменяя сам конец строки (или какой-либо сторонней программой/кодом). Эта проблема приводит к тому, что моя программа на С++ выполняет ввод/вывод текстовых файлов.

Ответ 1

Извините за частичное совпадение с другими ответами, но ради полноты:

Миф: endl является более переносимым, поскольку он записывает строку, заканчивающуюся в зависимости от соглашения о платформе.

Правда: endl определяется для записи '\n' в поток, а затем вызывает flush. Поэтому на самом деле вы почти никогда не хотите его использовать.

Заблуждение:. Вы должны открывать файлы в текстовом режиме для записи текста и в двоичном режиме для записи двоичных данных.

Правда: Текстовый режим существует в первую очередь, потому что некоторое время назад существовали файловые системы, которые различали текстовые файлы и двоичные файлы. Это уже не так на любой разумной платформе, которую я знаю. Вы также можете написать текст в двоично-открытых файлах. На самом деле это то, что вы хотите сделать, поскольку оно имеет более четкую семантику и приводит к более переносимому коду. Обратите внимание, что POSIX не различает двоичный и текстовый режим.

Как сделать текст: Откройте все в двоичном режиме и используйте обычный-старый '\n'. Вам также нужно будет беспокоиться о кодировке. Стандартизируйте UTF-8 для корректности Юникода. Использовать кодированные узкие строки UTF-8 внутри вместо wchar_t, который отличается на разных платформах. Ваш код станет легче переносить.

Совет.. Вы можете заставить MSVC по умолчанию открывать все файлы в двоичном режиме. Он должен работать следующим образом:

#include <stdio.h>
#include <iostream>
int main() {
    _fmode = _O_BINARY;
    std::ofstream f("a.txt"); // opens in binary mode
}

В качестве альтернативы можно использовать любые способы описанные здесь.

Ответ 2

Проблема не связана с endl вообще, ее переформатирование строк текстовых потоков прерывается в зависимости от системного стандарта.

Если вы этого не хотите, просто не используйте текстовые потоки - используйте двоичные потоки. То есть, откройте свои файлы с помощью флага ios::binary.

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

Это, кстати, то, что делает любой достойный текстовый редактор (но опять же, по умолчанию notepad.exe в Windows не является достойным текстовым редактором и не будет правильно обрабатывать разрывы строк Unix).

Ответ 3

Если вы действительно просто хотите ASCII LF, самый простой способ - открыть файл в двоичном режиме: в недвоичном режиме \n заменяется конкретным концом последовательности строк (например, его можно заменить на LF/CR или CR/LF, а в UNIX - обычно LF). В двоичном режиме это не делается. Отключение замены также является единственным эффектом двоичного режима.

BTW, использование endl эквивалентно записи a\n, за которым следует промывка потока. Обычно непреднамеренный флеш может стать серьезной проблемой производительности. Таким образом, endl следует использовать редко и только тогда, когда предназначен флеш.