c++ - 程序应该显示文件的最后 5 行,但不适用于大文件

标签 c++ linux

我编写了一个程序,应该打印文件的最后 5 行,但老师创建了一个 4 GB 行的文件,程序崩溃了。如何重写程序,使其可以处理非常大的文件

一个可能的解决方案是逐字符读取文件,但我不知道该怎么做

这里是c++程序代码

#include <iostream>

#include <fstream>

#include <string>

using std::ifstream;
using std::cout;
using std::string;
using std::getline;

int main(int argc, char * argv[], char * env[]) {
  setlocale(LC_ALL, "");
  int i;
  string line;

  if (argc == 3) {

    string filename = argv[1];

    ifstream myfile(filename);
    string n = argv[2];

    int nn = atoi(n.c_str());

    string line, buffer[nn];
    const size_t size = sizeof buffer / sizeof * buffer;
    size_t i = 0;

    while (getline(myfile, line)) {
      buffer[i] = line;
      if (++i >= size) {
        i = 0;
      }
    }

    for (size_t j = 0; j < size; ++j) {
      cout << buffer[i] << "\n";
      if (++i >= size) {
        i = 0;
      }
    }
    //return 0;

  }

}

最佳答案

问题肯定出在 4GB 文件中的大行上。您的解决方案缓冲(然后删除)每一行,并且至少其中一行可能太长而无法在您正在运行的计算机中缓冲,从而导致程序崩溃。

您应该从末尾开始读取文件,计算换行符的数量,并在达到 nn + 1 的计数时停止并输出 if 的其余部分。当您需要处理大行时,缓冲最后 nn 行并不是一个好的选择。

这里是一个可以帮助您的解决方案片段:

array<char, 64 * 1024> buffer; // 64kb of buffer

size_t nn = atoi(n.c_str()); 

myfile.seekg(0, ios_base::end); 

unsigned int nlcount = 0; 
size_t length = myfile.tellg(); 
size_t oldpos = length; 

while (myfile.tellg() > 0) { 
  size_t newpos = oldpos - min(oldpos, buffer.size()); 
  myfile.seekg(newpos); 
  size_t rdsize = oldpos - newpos; 
  myfile.read(buffer.data(), rdsize); 
  if (!myfile) { 
    cerr << "failed while looking for newlines\n"; 
    return 1; 
  } 
  auto rit = buffer.rbegin() + (buffer.size() - rdsize); 
  while (rit != buffer.rend() && nlcount <= nn) { 
    if (*rit == '\n') { 
      ++nlcount; 
    } 
    ++rit; 
  } 
  if (nlcount > nn) { 
    myfile.seekg(newpos + (buffer.rend() - rit) + 1); 
    break; 
  } 
  oldpos = newpos; 
} 

如果nlcount等于nn + 1,这会将输入流指向您只需要输出其余部分的确切位置嗯>。我建议您不使用缓冲行输出它,而是使用固定大小的缓冲区:

while (myfile.peek() != EOF) {
  myfile.read(buffer.data(), buffer.size());
  cout.write(buffer.data(), myfile.gcount());
}

不要使用getline(),否则在处理长行时您仍然会缓冲行并崩溃。

关于c++ - 程序应该显示文件的最后 5 行,但不适用于大文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58835047/

相关文章:

c++ - 如何修复错误 : unknown type name ‘namespace’

c++ - 如何仅将整数从文件读取到也包含字符串的c++程序中?

c++ - 未在此范围内声明的函数和变量(c++)

linux - 在linux中打印文件的最后2行

linux - 为什么 Docker 容器无法相互通信?

c++ - 包含的功能在以后的范围内不可用

c++ - 通过调用 CreateRemoteThread : crash 弹出 dll

python - 如何在Linux上使用python检测系统ACPI G2/S5软关闭事件

linux - 文件意外结束

linux - 在 USR1 信号后可靠地终止 sleep 进程