Использование getline при чтении из текстового файла

Сначала я создаю индексоподобный механизм, читаю каждую строку текстового файла с помощью getline, проверяю, соответствует ли она известному объявлению заголовка (string.compare), и сохраняю позицию в качестве индекса для этой точки. Затем я намерен использовать seekg(index,ios::beg) для поиска места в файле, где находится заголовок. После прочтения файла один раз при построении моего индекса и вызове seekg(0,ios::beg) следующая строка getline возвращает пустую строку, где я ожидаю увидеть первую строку в файле.

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

//build the index
while (! m_fileIn.eof())
{
   getline (m_fileIn,lineRead);
   int lineID = getLineID(lineRead);
   if(lineID==1)       //if its an STRM 
   {
   //save the index
   }
}

// start reading the file data
m_fileIn.seekg(0,ios::beg);
//read first line (title)

функция getLineID возвращает int в зависимости от результата сравнения строк.

неправильно ли использовать getline, если мне нужно перечитать файл?


person Dougie    schedule 31.08.2010    source источник
comment
Как вы читаете информацию из файла после создания индекса?   -  person Marc-Christian Schulze    schedule 31.08.2010
comment
Я снова использую функцию getline   -  person Dougie    schedule 31.08.2010


Ответы (2)


Ваша проблема вызвана тем, что внутри потока установлен бит Bad.
Операции с потоком будут игнорироваться до тех пор, пока бит Bad не будет сброшен.

// After the loop reset the Bad Bits.
m_fileIn.clear()

Примечание. Плохой бит — это одно из многих состояний ошибки, включая EOF.

Но это не ваши основные проблемы:

Вы используете Classic anti pattern для чтения файла:
Лучше используйте это.

while (getline (m_fileIn,lineRead))
{
   int lineID = getLineID(lineRead);
   if(lineID==1)       //if its an STRM 
   {
   //save the index
   }
}

Проблема в том, что EOF не устанавливается до тех пор, пока вы не прочитаете его.
Последнее действительное чтение читается UPTO, но не после EOF (поэтому EOF не установлен).

Итак, рассмотрим ситуацию, когда вы прочитали последнюю строку в файле. EOF не был установлен, так как вы его не прочитали. Итак, петля введена. Теперь вы выполняете getline(). Это пытается прочитать прошлое EOF, поскольку нет абсолютно никаких данных для чтения (ни одного байта). Таким образом, getline() терпит неудачу, теперь вы вызываете getlineID(), используя lineRead, значение которого неопределенно (стандарт не говорит, что происходит с lineRead при выполнении условия EOF; но он, вероятно, имеет значение последней прочитанной строки, поскольку вы не кажетесь чтобы сбросить его внутри цикла).

Другая проблема с этим кодом заключается в том, что он проверяет только EOF. Что происходит, когда возникает ошибка другого типа? Цикл фактически застревает в бесконечном цикле; это связано с тем, что при установке флага ошибки чтение больше не происходит, поэтому вы никогда не сможете добраться до EOF.

while (! m_fileIn.eof())
{
   getline (m_fileIn,lineRead)
   int lineID = getLineID(lineRead);
   if(lineID==1)       //if its an STRM 
   {
   //save the index
   }
}

Решение состоит в том, чтобы выполнить операцию чтения в цикле while. Это работает, потому что getline() возвращает поток, переданный в качестве первого параметра. Поэтому поток используется в логическом контексте. Когда поток используется в логическом контексте, он преобразуется в тип, который можно использовать как логический; значение этого объекта эквивалентно true, если ошибок нет, и false в противном случае.

В этой ситуации предпринимается попытка чтения, но если это не удается, цикл никогда не запускается.

person Martin York    schedule 31.08.2010

После размещения здесь и просмотра различных веб-сайтов я добавил строку

m_fileIn.clear();

перед линией

getline (m_fileIn,lineRead);

очистив флаги ошибок (я предполагаю ошибку eof), я смог продолжить как обычно.

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

person Dougie    schedule 31.08.2010
comment
Это антишаблон :- while (! m_fileIn.eof()) Не используйте его. Этот анти-шаблон не специфичен для С++, а является общим для всех языков (я знаю). Из Perl -> Php -> Python -> C -> Java -> Fortran и т. д. Файлы всегда читаются одинаково (выполняйте операцию чтения как часть условного выражения цикла). - person Martin York; 31.08.2010