Я пытаюсь написать простую программу хвоста в C++. Я пробовал пример из этого решения, и он работает как шарм.
Затем я попытался сделать ifstream
глобальным. Теперь код больше не работает, и ничего не отображается, если я редактирую файл.
Почему это поведение? Я прочитал руководство ifstream::open
и я не вижу никакой ошибки, но код не работает:
Открывает файл, идентифицированный именем файла аргумента, связав его с объектом потока, так что операции ввода/вывода выполняются над его содержимым. Режим аргумента указывает режим открытия.
Вот нерабочий код:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int find_last_linefeed(ifstream &infile) {
infile.seekg(0,ios::end);
int filesize = infile.tellg();
for(int n=1;n<filesize;n++) {
infile.seekg(filesize-n-1,ios::beg);
char c;
infile.get(c);
if(c == 0x0A) return infile.tellg();
}
}
ifstream infile;
int main() {
int last_position=-1;
for(;;) {
infile.open("/Users/alberto/tmp/test");
int position = find_last_linefeed(infile);
if(position > last_position) {
infile.seekg(position,ios::beg);
string in;
infile >> in;
cout << in << endl;
}
last_position=position;
sleep(1);
}
}
Вот рабочий код:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int find_last_linefeed(ifstream &infile) {
infile.seekg(0,ios::end);
int filesize = infile.tellg();
for(int n=1;n<filesize;n++) {
infile.seekg(filesize-n-1,ios::beg);
char c;
infile.get(c);
if(c == 0x0A) return infile.tellg();
}
}
int main() {
int last_position=-1;
for(;;) {
ifstream infile;
infile.open("/Users/alberto/tmp/test");
int position = find_last_linefeed(infile);
if(position > last_position) {
infile.seekg(position,ios::beg);
string in;
infile >> in;
cout << in << endl;
}
last_position=position;
sleep(1);
}
}
Поскольку вы open
внутри цикла, поток войдет в состояние ошибки на второй итерации и продолжит сбой после этого.
Переехать
infile.open("/Users/alberto/tmp/test");
вне цикла, или определите infile
как это, и вообще не используйте open
:
ifstream infile("/Users/alberto/tmp/test");
Лучшая альтернатива - вообще не использовать глобальную переменную, так как здесь нет оснований.
Кроме того, find_last_linefeed
не возвращает ничего, если файл не содержит строку, которая не определена.
-
Что касается ifstream::open
, из стандарта (27.9.1.9):
Вызывает rdbuf() → open (s, mode | ios_base :: in). Если эта функция не возвращает нулевой указатель, вызовите clear(), в противном случае вызовы setstate (failbit)
и basic_filebuf::open
(27.9.1.4):
Если is_open()! = False, возвращает нулевой указатель
std::basic_filebuf::open
, повторное открытие не должно вести себя так, как вы описали, но должно возвращать null
и продолжать работать.