c ++只读取最后一行文本文件的最快方法?

use*_*171 9 c++ iostream seek

我想只阅读文本文件的最后一行(我在UNIX上,可以使用Boost).我所知道的所有方法都需要扫描整个文件以获得最后一行,这根本没有效率.有没有一种有效的方法来获得最后一行?

此外,我需要它足够健壮,即使有问题的文本文件经常被另一个进程附加,它也能正常工作.

der*_*ace 18

使用seekg跳转到文件的末尾,然后回读,直到找到第一个换行符.下面是使用MSVC的一些示例代码.

#include <iostream>
#include <fstream>
#include <sstream>

using namespace std;

int main()
{
    string filename = "test.txt";
    ifstream fin;
    fin.open(filename);
    if(fin.is_open()) {
        fin.seekg(-1,ios_base::end);                // go to one spot before the EOF

        bool keepLooping = true;
        while(keepLooping) {
            char ch;
            fin.get(ch);                            // Get current byte's data

            if((int)fin.tellg() <= 1) {             // If the data was at or before the 0th byte
                fin.seekg(0);                       // The first line is the last line
                keepLooping = false;                // So stop there
            }
            else if(ch == '\n') {                   // If the data was a newline
                keepLooping = false;                // Stop at the current position.
            }
            else {                                  // If the data was neither a newline nor at the 0 byte
                fin.seekg(-2,ios_base::cur);        // Move to the front of that data, then to the front of the data before it
            }
        }

        string lastLine;            
        getline(fin,lastLine);                      // Read the current line
        cout << "Result: " << lastLine << '\n';     // Display it

        fin.close();
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

以下是测试文件.它在文本文件中以空,一行和多行数据成功.

This is the first line.
Some stuff.
Some stuff.
Some stuff.
This is the last line.
Run Code Online (Sandbox Code Playgroud)

  • 有趣,我在发布前测试过它.你的test.txt最后有一个额外的空行吗? (3认同)
  • 所以,我实际测试了它,它实际上没有用.lastLine始终为空. (2认同)
  • 它对我也不起作用,直到我在第一次调用“seekg”函数时替换了“-1”,即“fin.seekg(-1,ios_base::end);”就在“ bool keepLo​​oping = true;`,带有“-2”。 (2认同)

小智 5

最初,这是为了读取最后一个系统日志条目而设计的。鉴于 EOF 之前的最后一个字符是'\n'我们向后查找下一个出现的字符'\n',然后将该行存储到字符串中。

#include <fstream>
#include <iostream>

int main()
{
  const std::string filename = "test.txt";
  std::ifstream fs;
  fs.open(filename.c_str(), std::fstream::in);
  if(fs.is_open())
  {
    //Got to the last character before EOF
    fs.seekg(-1, std::ios_base::end);
    if(fs.peek() == '\n')
    {
      //Start searching for \n occurrences
      fs.seekg(-1, std::ios_base::cur);
      int i = fs.tellg();
      for(i;i > 0; i--)
      {
        if(fs.peek() == '\n')
        {
          //Found
          fs.get();
          break;
        }
        //Move one character back
        fs.seekg(i, std::ios_base::beg);
      }
    }
    std::string lastline;
    getline(fs, lastline);
    std::cout << lastline << std::endl;
  }
  else
  {
    std::cout << "Could not find end line character" << std::endl;
  }
  return 0;
}
Run Code Online (Sandbox Code Playgroud)