我正在尝试从正在增长的文件中读取(类似于tail -F
的内容),但我的代码必定存在一些问题:
string log, logFile("test.log");
size_t p = 0;
while(true)
{
ifstream ifs(logFile.c_str());
ifs.seekg(p); //*1
while(ifs.eof() == false)
{
getline(ifs, log);
cout << log << endl;
p = ifs.tellg(); //*2
}
nanosleep(&pause, NULL);
}
如果没有// * 1和// * 2的行,日志文件会被正确读取到最后,但如果添加了新行,则没有任何反应。
使用seekg和tellg我试图存储文件的当前结束位置,这样当我重新打开它时,我可以去那里看看已添加的内容。
我想知道我的代码有什么问题,如果真的有必要为此目的关闭并重新打开同一个文件。
谢谢。
答案 0 :(得分:15)
循环不正确,因为遇到eof()
时tellg()
返回-1
并且在调用eof()
之后没有立即检查getline()
需要是。将循环更改为:
while (getline(ifs, log))
{
cout << log << endl;
p = ifs.tellg();
}
此外,当p
返回size_t
时,tellg()
被声明为-1
,p
的值被设置为4294967295
。这意味着seekg()
被设置为超出文件末尾。将p
的类型更改为std::streamoff
并确认对seekg()
的调用是否成功:
if (ifs.seekg(p))
{
while (getline(ifs, log))
{
cout << log << endl;
p = ifs.tellg();
}
}
如果确实有必要为此目的关闭并重新打开同一个文件。
不,没有必要,但您需要从流中clear()
eof
状态。以下是已发布代码的更正版本的替代方法:
#include <iostream>
#include <string>
#include <fstream>
int main()
{
std::ifstream ifs("test.log");
if (ifs.is_open())
{
std::string line;
while (true)
{
while (std::getline(ifs, line)) std::cout << line << "\n";
if (!ifs.eof()) break; // Ensure end of read was EOF.
ifs.clear();
// You may want a sleep in here to avoid
// being a CPU hog.
}
}
return 0;
}
答案 1 :(得分:3)
由于这些答案都不起作用,我想出了一个有效的方法......
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
string log, logFile("test.txt");
std::streamoff p = 0;
ifstream ifs(logFile.c_str());
while(true)
{
ifs.seekg(p); //*1
while (getline(ifs, log))
{
cout << log << endl;
if(ifs.tellg() == -1) p = p + log.size();
else p = ifs.tellg();
}
ifs.clear();
}
}
答案 2 :(得分:0)
此代码适用于我:
struct timespec pause;
pause.tv_sec = 1;
pause.tv_nsec = 0;
std::ifstream ifs("test.log");
std::streamoff p;
if(ifs.is_open())
{
std::string line;
while(true)
{
if(ifs.seekg(p))
{
while(std::getline(ifs, line))
{
std::cout << line << std::endl;
p = ifs.tellg();
}
}
ifs.clear();
nanosleep(&pause, NULL);
}
}