Кросс-платформенный беспорядок новой строки - PullRequest
11 голосов
/ 07 ноября 2011

По какой-то причине моя функция записи в текстовый файл внезапно перестала работать.

void write_data(char* filename, char* writethis)
{
    ofstream myfile;
    myfile.open (filename, std::ios_base::app);
    myfile << endl << writethis;
    myfile.close();
}

Функция была вызвана из цикла, поэтому в основном она начиналась с пустой строки и добавляла все следующие строки "writeethis" в новой строке.

Тогда внезапно, никаких новых строк. Весь текст был добавлен в одну строку. Поэтому я немного покопался и наткнулся на это:

  1. Windows = CR LF
  2. Linux = LF
  3. MAC <0SX = CR </li>

Итак, я изменил строку на

myfile << "\r\n" << writethis;

И это снова сработало. Но сейчас я в замешательстве. Я пишу на Linux , но я читаю текстовые файлы, созданные с помощью программы на Windows после передачи их с filezilla . Теперь, какая часть этого заставила строки в текстовом файле появиться как одна строка?

Я был почти уверен, что "endl" отлично работает для linux, так что теперь я думаю, что windows испортила файл после передачи их с помощью filezilla? Если испортить способ записи (и чтения) текстового файла, моя программа будет повреждена, поэтому, если кто-то сможет это объяснить, я буду признателен.

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

Edit: Я попытался поменять режим передачи с ASCII / Binary (даже удалил force-ASCII-for-txt-extension), но он не делает различий. Новые строки появляются в Linux, но не в Windows. fz-messup

Как странно.

Ответы [ 4 ]

10 голосов
/ 07 ноября 2011

В результате получается, что вы пишете окончания строк Unix ('\ n'), затем переносите их на компьютер с Windows, получая битовый идентичный файл, затем пытаетесь открыть файл с помощью программы просмотра, которая не понимает окончания строк Unix ( Блокнот скорее всего).

Из моего опыта написания переносимого кода:

  • Стандартизировать на ОДНОМ конце строки ('\n', LF) на ВСЕХ платформах.
  • Всегда открывайте файлы в двоичном формате, даже если вы пишете текст.
  • Пусть пользователь, открывающий файл, использует средство просмотра текста, которое понимает любые окончания строк. Есть много возможностей для Windows (включая Visual Studio, Notepad ++, Wordpad и ваш любимый браузер).

Да, я думаю, что для всех есть больше преимуществ, чтобы стандартизировать одну вещь , чем поддерживать их всех повсюду. Также я отрицаю существование «правильных окончаний строк на правильной платформе». Тот факт, что Microsoft решила, что их родной API не говорит на UTF-8 или не понимает окончания строк Unix, не мешает сделать это всем в Windows. Только убедитесь, что вы не передали этот материал в WinAPI. Много раз вы выполняете обработку текста на своих внутренних данных, которые система никогда не увидит, так зачем, черт возьми, вам нужно усложнять свою жизнь, оправдывая ожидания внутренних органов этой системы?

6 голосов
/ 07 ноября 2011

endl делает"отлично работает для Linux".Поток endl передает поток \n символа и очищает поток.Всегда.

Тем не менее, поток файлов в текстовом режиме преобразует это \n в \r\n на уровне реализации в Windows, и вы часто найдете преобразования концов строк при передаче файла между платформами.тоже.

Это, вероятно, не проблема C ++, и ничто не "сломано";вам, вероятно, следует настроить FileZilla для обработки вашего файла как text , а не как " binary " (режим, в котором окончания строк не преобразуются).Если ваш файл не имеет расширения имени, например ".txt", то он, вероятно, не делает этого по умолчанию.

3 голосов
/ 07 ноября 2011

FTP может испортить ваши файлы (то есть, он преобразует переводы строки), если вы передаете файлы как ASCII. Попробуйте передать как BIN (двоичный файл).

2 голосов
/ 07 ноября 2011

Внутренне все приложения используют '\ n' для обозначения завершения строки.

Проблема заключается в том, что последовательность завершения строки зависит от платформы для текстовых файлов (как показало ваше исследование) ПримечаниеТекстовые файлы, это формат по умолчанию при открытии файла.Если вы явно выбираете двоичный файл при открытии файла, при чтении / записи не происходит перевода.

На самом деле это означает, что символ '\ n' преобразуется в специфическую для платформы последовательность символов при записи его вфайл.Но также обратите внимание, что эта специфичная для платформы последовательность преобразуется обратно в '\ n' при чтении файла.Проблема, с которой вы сталкиваетесь, заключается в том, что вы записали файлы на одной платформе и прочитали их на другой.

В Linux последовательность завершения строки - LF ('\ n').Таким образом, вы пишете файл, и все символы \ n преобразуются в символы LF.Вы переносите эти файлы в систему Windows и теперь читаете файл.В Windows последовательность завершения строки - «CRLF». Поэтому редактор, который читает файл, ищет два символа для преобразования обратно в «\ n», но не находит эти символы.Теперь все зависит от того, насколько умен редактор, получая одну или несколько строк.

...