在C++中是否有实现等同于'tail -n'命令的功能的数据结构?

Is there a data structure for implementing a function equivalent to 'tail -n' command in C++?

我想编写一个等同于 C++ 中的 Linux tail -n 命令的函数。虽然,我逐行解析了该文件的数据,从而增加了行数,但如果文件大小变得非常大(~千兆字节),这种方法将花费很多时间!有没有更好的方法或数据结构来实现这个功能?

这是我的两种方法:

int File::countlines()
{
    int lineCount = 0;
    string str;

    if (file)
       {
            while (getline(file, str))
            {
                lineCount += 1;
            }
     }
   return lineCount;
}

void File::printlines()
{
    int lineCount = 0;
    string line;

    if (file)
    {
        lineCount = countlines();

        file.clear();
        file.seekg(ios::beg);

        if (lineCount <= 10)
        {
             while (getline(file, line))
             {
                 cout << line << endl;
             }
        }
        else
        {
            int position = lineCount - 10;
            while (position--)
            {
                getline(file, line);
            }
           while (getline(file, line))
           {
               cout << line << endl;
           }
       }
}
}

如果文件变大,这种方法很耗时,所以我想要么用其他数据结构替换它,要么写一个更高效的代码。

使你的程序变慢的一个原因是读取文件两次,所以你可以保留最后 n 个 EOL 位置(在你的程序中 n=10),最方便的数据结构是循环缓冲区,但这据我所知,标准库没有提供(boost 有一个)。它可以通过大小为 n 的 std::vector 来实现,索引在递增后对 n 取模。

使用该循环缓冲区,您可以立即跳转到文件中的最低偏移量(如果缓冲区已满,则为下一个偏移量)并打印所需的行。

完成此操作后,我对一行的最大长度(例如,一千字节)做了一个慷慨的估计,seek编辑到距末尾的那个距离,并开始阅读行进入循环缓冲区,直到文件结束。

几乎 每种情况下,您都会得到超过 n 行,因此您只需打印出循环缓冲区的内容,就大功告成了。但是请注意,您确实需要确保阅读的内容 n 行多 行,而不仅仅是 n 行。您阅读的第一行通常只是部分行,因此如果您正好阅读 n 行,第一行可能只是部分行。

在极少数情况下,您没有获得所需的行数,因此您向后搜索两倍(或您选择的其他因素),然后重新开始。如果你真的想花哨的话,你可以根据你读过的行的平均长度来推断你需要的行数(但老实说,这种情况很少见,不值得做很多工作来优化它).

无论文件大小如何,这通常基本上立即生效。我想(理论上)对于一个行数非常长的文件,它会变慢,但如果是这样,用户可能犯了一个错误,并试图拖尾不是文本文件的东西(这通常是无用的无论如何)。