std :: getline и eol vs eof - PullRequest
       18

std :: getline и eol vs eof

0 голосов
/ 06 августа 2009

У меня есть программа, которая отслеживает растущий файл.

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

Есть ли вменяемый способ сделать это?

Вот что я пытаюсь:

if (getline (stream, logbuffer))
{
    if (stream.eof())
    {
        cout << "Partial line found!" << endl;
        return false;
    }
    return true;
}
return false;

Однако я не могу легко воспроизвести проблему, поэтому я не уверен, что обнаружил ее с помощью этого кода. std :: getline удаляет символы новой строки, поэтому я не могу проверить буфер на наличие новой строки. Мое сообщение журнала (выше) никогда не отключается.

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

Спасибо.

Ответы [ 4 ]

3 голосов
/ 06 августа 2009

Это никогда не будет правдой:

if (getline (stream, logbuffer))
{
    if (stream.eof())
    {
       /// will never get here

Если getline() сработало, поток не может быть в состоянии eof. Тесты eof() и связанные состояния работают только с результатами предыдущей операции чтения, такой как getline() - они не предсказывают, что будет делать следующее чтение.

Насколько я знаю, нет способа делать то, что вы хотите. Однако, если другой процесс записывает строку за раз, проблемы, которые, по вашему мнению, вы испытываете, должны быть очень редкими (по моему опыту отсутствуют), в некоторой степени зависящими от используемой вами ОС. Я подозреваю, что проблема кроется в другом месте, возможно, в вашем коде. Хвост файла является очень распространенной вещью, и обычно для этого не нужно прибегать к специальному коду.

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

forever do
   wait for file change
   read all possible input using read or readsome (not getline)
   chop input into lines and possible partial line
   process as required
end
1 голос
/ 06 августа 2009

Объект istream, такой как std::cin, имеет функцию get , которая прекращает чтение при переходе на новую строку без извлечения его из потока. Затем вы можете peek() или get() проверить, действительно ли это перевод строки. Подвох в том, что вам нужно знать максимальную длину строки, приходящей из другого приложения. Пример (непроверенный) кода приведен ниже:

char buf[81];  // assumes an 80-char line length + null char
memset(buf, 0, 81);

if (cin.get(buf, 81))
{
    if (cin.peek() == EOF)  // You ran out of data before hitting end of line
    {
        cout << "Partial line found!\n";
    }
}
0 голосов
/ 06 августа 2009

Я должен не согласиться с одним заявлением, которое вы сделали здесь:

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

Похоже, из того, что вы сказали, было бы очень легко воспроизвести вашу проблему, если бы вы это сказали. Вы можете легко создать текстовый файл в каком-либо текстовом редакторе - просто убедитесь, что последний аналог заканчивается EOF вместо перехода на новую строку. Затем укажите вашей программе на этот файл и посмотрите, что получится.

0 голосов
/ 06 августа 2009

Даже если другая программа не закончила запись файла, в файле, где заканчивается строка, поэтому нет никакой возможности определить разницу, кроме как ждать, пока другая программа не напишет что-то новое.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...