将整个文件读入行向量的最有效方法

Most efficient way to read an entire file into vector of lines

本文关键字:向量 有效 方法 文件      更新时间:2023-10-16

我正试图找到一种更有效的方法将整个文件读取为行向量,定义为std::vector<std::string>

目前,我已经写了幼稚的:

std::ifstream file{filepath};
std::vector<std::string> lines;
std::string line;
while(std::getline(file, line)) lines.push_back(line);

但是我觉得push_back中额外的复制和每行的向量重新分配对效率非常不利,我正在寻找一种更现代的c++类型的方法,例如在复制字节时使用流缓冲区迭代器:

std::ifstream file{filepath};
auto filesize = /* get file size */;
std::vector<char> bytes;
bytes.reserve(filesize);
bytes.assign(std::istreambuf_iterator{file}, istreambuf_iterator{});

是否有这样的方式,我可以读取文本文件在行成一个矢量?

有一种非常有趣且相对较新的方法——range。你可以阅读Eric Niebler写的非常有趣的文章:

关于快速getlines替代

的Out参数、Move语义和状态算法

输入迭代器与输入范围

下面的代码可以工作。

struct FileContents
{
   // Contents of the file.
   std::string contents;
   // Each line consists of two indices.
   struct line { std::string::size_type begin; std::string::size_type end;};
   // List of lines.
   std::vector<line> lines;
};
void readFileContents(std::string const& file,
                      FileContents& fileContents)
{
   std::ifstream ifs(file);
   if ( !ifs )
   {
      // Deal with error.
      return;
   }
   // Get the size of the file.
   ifs.seekg(0, std::ios::end);
   std::fstream::pos_type size = ifs.tellg();
   // Reserve space to read the file contents.
   fileContents.contents.assign(static_cast<std::string::size_type>(size), '');
   // Read the file contents.
   ifs.seekg(0, std::ios::beg);
   ifs.read(&fileContents.contents[0], size);
   ifs.close();
   // Divide the contents of the file into lines.
   FileContents::line line = {0, 0};
   std::string::size_type pos;
   while ( (pos = fileContents.contents.find('n', line.begin)) != std::string::npos )
   {
      line.end = pos+1;
      fileContents.lines.push_back(line);
      line.begin = line.end;
   }
   line.end = fileContents.contents.size();
   if ( line.begin < fileContents.contents.size() )
   {
      fileContents.lines.push_back(line);
   }
}