获取c++文本文件的第n行

Getting the nth line of a text file in C++

本文关键字:文件 c++ 文本 获取      更新时间:2023-10-16

我需要读取文本文件的第n行(例如textfile.findline(0)会找到ifstream textfile加载的文本文件的第一行)。这可能吗?我不需要将文件的内容放入数组/向量中,我只需要将文本文件的特定行分配给变量(特别是int)。

注:我正在寻找最简单的解决方案,不需要我使用任何大的外部库(例如Boost)

这个怎么样?

std::string ReadNthLine(const std::string& filename, int N)
{
   std::ifstream in(filename.c_str());
   std::string s;
   //for performance
   s.reserve(some_reasonable_max_line_length);    
   //skip N lines
   for(int i = 0; i < N; ++i)
       std::getline(in, s);
   std::getline(in,s);
   return s; 
}

如果要读取第n行开头,可以使用stdin::ignore跳过前n-1行,然后从下一行读取并赋值给变量。

template<typename T>
void readNthLine(istream& in, int n, T& value) {
  for (int i = 0; i < n-1; ++i) {
    in.ignore(numeric_limits<streamsize>::max(), 'n');
  }
  in >> value;
}

Armen的解决方案是正确的答案,但我认为我应该抛出一个替代方案,基于jweyrich的缓存想法。无论好坏,这在构建时读取整个文件,但只保存换行符位置(不存储整个文件,因此对于大文件来说效果很好)。然后您可以简单地调用ReadNthLine,它将立即跳转到该行,并读入您想要的一行。另一方面,只有在每次只获取一小部分行,并且在编译时不知道行号的情况下,这才是最优的。

class TextFile {
    std::ifstream file_stream;
    std::vector<std::ifstream::streampos> linebegins;
    TextFile& operator=(TextFile& b) = delete;
public;
    TextFile(std::string filename) 
    :file_stream(filename) 
    {
        //this chunk stolen from Armen's, 
        std::string s;
        //for performance
        s.reserve(some_reasonable_max_line_length); 
        while(file_stream) {
            linebegins.push_back(file_stream.tellg());
            std::getline(file_stream, s);
        }
    }
    TextFile(TextFile&& b) 
    :file_stream(std::move(b.file_stream)), 
    :linebegins(std::move(b.linebegins))
    {}
    TextFile& operator=(TextFile&& b) 
    {
        file_stream = std::move(b.file_stream);
        linebegins = std::move(b.linebegins);
    }
    std::string ReadNthLine(int N) {
        if (N >= linebegins.size()-1)
            throw std::runtime_error("File doesn't have that many lines!");
        std::string s;
        // clear EOF and error flags
        file_stream.clear();
        file_stream.seekg(linebegins[N]);
        std::getline(file_stream, s);
        return s;
    }
};

这当然有可能。有(n-1)第n行之前的'n'字符。一直读到你要找的那个。您可以动态地执行此操作,而不需要存储除正在考虑的当前行之外的任何内容。