c++ - 如何在 C++ 中读取不断增长的文本文件?

标签 c++ logging stl fstream seekg

我正在尝试读取一个正在增长的文件(类似于 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,我试图存储文件的当前结束位置,这样当我重新打开它时,我可以直接到那里并读取已添加的内容。

我想知道我的代码有什么问题,以及是否真的有必要为此关闭并重新打开同一个文件。

谢谢。

最佳答案

遇到 eof() 时循环不正确 tellg()返回 -1 并且在调用 getline() 之后没有立即检查 eof(),而这是需要的。将循环更改为:

while (getline(ifs, log))
{
    cout << log << endl;
    p = ifs.tellg();
}

此外,当 tellg() 返回 -1 的值时,p 被声明为 size_t p 被设置为 4294967295。这意味着 seekg() 被设置为超出文件末尾。将 p 的类型更改为 std::streamoff 并确认对 seekg() 的调用成功:

if (ifs.seekg(p))
{
    while (getline(ifs, log))
    {
        cout << log << endl;
        p = ifs.tellg();
    }
}

if it is really necessary to close and reopen the same file for this purpose.

不,这不是必需的,但您需要从流中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;
}

关于c++ - 如何在 C++ 中读取不断增长的文本文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11757304/

相关文章:

c++ - 对单个结构字段的下标访问

c++ - 是否有 STL 算法来查找序列中值的最后一个实例?

c++ - 带有MinGW STL的Clang(错误: no member named 'fgetws' in the global namespace)

c++ - 使用较小的数组初始化 C++ std::array

c++ - 无法更新控制台应用程序中的窗口

c++ - 继承并从基类中选择构造函数

c++ - 服务的静态和动态演化

python - 两个 Pylons 记录器处理程序(Sentry/Raven 和控制台)用于相同的 qualname

java - 如何在本地计算机上启动logback + logstash?

sql - Azure SQL 创建数据库状态挂起