如何在c++中从最后一行读取文本文件

How to read a text file from the last line in C++?

本文关键字:一行 读取 文件 取文本 c++ 最后      更新时间:2023-10-16

我有一个像这样的文本文件:

1    0.05   -7  
2    0.1    -4  
3    0.11   -1   
4    0.12   -3   
3    0.15   -2
4    0.2    0  
5    0.25   8

我想要的是从最后一行读取c++中的文本文件,到达以4开头的行,将该行的值保存在数组中,然后继续到达以2开头的行,并再次保存与该行对应的值。

从最后一行开始对我来说非常重要,因为我要查找时间步骤4的最后更新值。从一开始的阅读给了我这个向量4 0.12 -3,而我正在寻找这个向量4 0.2 0

确实没有简单的方法可以做到这一点。除非文件非常大(100MGB或更多),最好的方法可能是简单地将整个内容读入一个矢量,然后在内存中处理它[按照您选择的顺序,因为您现在可以将其视为任何类型的矢量,因此可以"随机访问"]。

可以"从末尾向后移动",但很尴尬。像这样的代码将从后到前读取整个文件:

ifstream f("somefile.txt");
char c;
// Place get position at one from last. 
f.seekg(-1, ios_base::end);
while(f.get(c))
{
  ... process character ... 
  // Move back two (because get moved forward one, and
  // we want the one before that. 
  f.seekg(-2, ios_base::cur);
}

你必须记住你的字符串是向后输入的,所以你必须使用prepend而不是append。

我的点阵操作策略是逐行扫描所有文件,在内存中保存一个两行的数组,在每个传入行更新,以便始终包含最新的两行。在EOF,您的数组包含感兴趣的行。伪代码:

array[2];
array[0]=array[1]=null;
while(!eof)
{
   array[1]=array[0];
   array[0]=readline();
}
... do what you want with array[1] and array[0]

array[0]将包含文件的最后一行,array[1]是最后一行。检查是否为空:如果文件只包含一行,或者根本没有行,则可以让数组中的一个或两个条目指向空。当然,如果文件非常大,那么这样做会耗费时间,但是对于每次操作之间的时间间隔至少为几分钟的spot操作来说,这是一种简单可靠的解决方案。否则,如果需要更频繁的轮询,为什么不连续地监视文件呢?这是tail -f程序使用的一种策略。

在文本文件中跳转是很困难的,而且通常效率很低。我的建议如下:

  1. 将整个文件加载到内存中,只保留最近的结果:

    ifstream fin("fname.txt");
    // ... Don't forget error checking.
    std::unordered_map<int, std::pair<float, int>> entries;
    int first, third;
    float second;
    while (fin >> first >> second >> third) {
       entries[first] = make_pair(second, third); // Will overwrite existing.
    }
    
  2. 现在您可以通过访问您正在查找的键的映射轻松访问最后一个条目。

    cout << entries[4]->first << " " << entries[4]->second  << endl;
    

将输出:0.2 0

我想到了两个策略:

1-先前的建议:有大小为2或两个变量的数组,等等…,保存最后两行读取(如果文件很小,应该可以很好地工作,并且非常直接)

2 .使用ifstream::seekg(std::ios_base::end)在EOF中定位,并向后搜索EOL标记(如果文件大,行相对于文件小,这应该有效)。peek可以检查EOL标记(考虑到不同的EOL标记(nr, n, r),这更复杂,如果行太长,可能会很慢。