С++ getline читает весь файл

Я использую std::getline() для чтения из текстового файла построчно. Однако первый вызов getline — это чтение всего файла! Я также пытался явно указать разделитель как '\n'. Любые идеи, почему это может происходить?

Мой код:

std::ifstream serialIn;
...
serialIn.open(argv[3]);
...
std::string tmpStr;
std::getline(serialIn, tmpStr, '\n');
// All 570 lines in the file is in tmpStr!
...
std::string serialLine;
std::getline(serialIn, serialLine);
// serialLine == "" here

Я использую Visual Studio 2008. Текстовый файл имеет 570 строк (я просматриваю его в Notepad++).

Редактировать: я решил эту проблему, используя Notepad++, чтобы преобразовать окончания строк в моем входном текстовом файле в окончания строк «Windows». Файл был написан с '\n' в конце каждой строки с использованием кода C++. Почему getline() требует окончания строки Windows (\r\n)?? Это связано с шириной символа или реализацией Microsoft?


person voxoid    schedule 28.08.2012    source источник
comment
Не могли бы вы опубликовать первые 10 строк файла, пожалуйста.   -  person Fantastic Mr Fox    schedule 28.08.2012
comment
Я почти уверен, что getline() по умолчанию использует '\n' в качестве разделителя. Я не понимаю, почему возврат каретки повлияет на это.   -  person Rapptz    schedule 28.08.2012
comment
Стандартные функции библиотеки ввода/вывода читают и записывают окончания строк для платформы. Поэтому программы, созданные для среды выполнения Windows C или C++, ожидают окончание строк Windows (шокирует!).   -  person jamesdlin    schedule 28.08.2012
comment
Спасибо, Джеймсдлин. Думаю, ссылка на документацию, подтверждающую такое поведение, была бы полезнее сарказма.   -  person voxoid    schedule 28.08.2012


Ответы (2)


Просто догадываюсь, но может ли ваш файл иметь окончания строк Unix, а вы работаете в Windows?

person Nitzan Shaked    schedule 28.08.2012
comment
+1 Просто чтобы объяснить ... в UNIX / Linux один символ перевода строки (код ASCII 10) разделяет строки, тогда как в Windows ожидается как возврат каретки (13), так и перевод строки. Таким образом, если в вашем файле есть только символы перевода строки, они могут не распознаваться C++ как разделители строк, даже если некоторые редакторы распознают их и отобразят содержимое файла с предполагаемыми разрывами строк. - person Tony Delroy; 28.08.2012
comment
Чего я не понимаю, так это почему getline() требует окончания строки Windows (\r\n), когда в его документации говорится, что он использует только разделитель строк '\n' (Unix)? И, кроме того, я явно установил разделитель на «\ n», чтобы убедиться. Вы говорите, что действительно существует несоответствие между документацией и тем, как это работает на самом деле? Спасибо за ваш ответ. - person voxoid; 28.08.2012

Вы путаете перевод строки, который вы видите в коде ('\n'), с фактическим представлением конца строки для платформы (некоторая комбинация возврата каретки (CR) и перевода строки ( LF) байт).

Стандартные функции библиотеки ввода/вывода автоматически преобразовывают окончания строк для вашей платформы в концептуальные символы новой строки для потоков текстового режима (по умолчанию). См. В чем разница между текстовым и двоичным вводом-выводом? из часто задаваемых вопросов comp.lang.c. (Хотя это из FAQ по C, концепции применимы и к C++.) Поскольку вы работаете в Windows, стандартные функции ввода-вывода по умолчанию записывают новые строки как CR-LF и ожидают CR-LF для новых строк при чтении.

Если вы не хотите, чтобы эти преобразования выполнялись, и предпочитаете видеть необработанные, неискаженные данные, вам следует установить свои потоки в двоичный режим. В двоичном режиме \n соответствует только LF, а \r соответствует только CR.

В C вы можете указать двоичный режим, передав "b" в качестве одного из флагов в fopen:

FILE* file = fopen(filename, "rb"); // Open a file for reading in binary mode.

In C++:

 std::ifstream in;
 in.open(filename, std::ios::binary);

or:

 std::ifstream in(filename, std::ios::binary);
person jamesdlin    schedule 29.08.2012