关于c ++:将文件加载到vector

Loading a file into a vector

我想将文本文件的内容加载到vector(或任何可能的char输入迭代器中)中。 目前,我的代码如下所示:

1
2
3
4
5
6
7
8
std::vector<char> vec;
std::ifstream file("test.txt");
assert(file.is_open());
while (!(file.eof() || file.fail())) {
    char buffer[100];
    file.read(buffer, 100);
    vec.insert(vec.end(), buffer, buffer + file.gcount());
}

我不喜欢手动使用缓冲区(为什么要使用100个字符?为什么不建议使用200个字符,或者为什么不使用25个字符?),或者这样做占用了大量的行。 该代码看起来非常丑陋且非C ++。 是否有更直接的方法?


如果要避免逐个读取char:

1
2
3
4
5
6
7
8
9
if (!file.eof() && !file.fail())
{
    file.seekg(0, std::ios_base::end);
    std::streampos fileSize = file.tellg();
    vec.resize(fileSize);

    file.seekg(0, std::ios_base::beg);
    file.read(&vec[0], fileSize);
}


我认为是这样的,但是没有测试环境:

1
std::copy(std::istream_iterator<char>(file), std::istream_iterator<char>(), std::back_inserter(vec));

可能是您必须使用io机械手来处理诸如换行符/空格之类的事情。

编辑:如评论中所述,可能会影响性能。


另一种方法,首先使用rdbuf()将整个文件读取为std::stringstream

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <fstream>
#include <sstream>
#include <vector>
#include <string>

// for check:
#include
#include <iterator>
#include <iostream>

int main() {
   std::ifstream file("test.cc");
   std::ostringstream ss;
   ss << file.rdbuf();
   const std::string& s = ss.str();
   std::vector<char> vec(s.begin(), s.end());

   // check:
   std::copy(vec.begin(), vec.end(), std::ostream_iterator<char>(std::cout));
}

使用迭代器:

1
2
3
4
5
#include <iterator>

istream_iterator<char> data( file );
istream_iterator<char> end;
vec.insert( std::back_inserter(vec), data, end );


有很多好的回应。 谢谢大家! 我决定使用的代码是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
std::vector<char> vec;
std::ifstream file;
file.exceptions(
    std::ifstream::badbit
  | std::ifstream::failbit
  | std::ifstream::eofbit);
//Need to use binary mode; otherwise CRLF line endings count as 2 for
//`length` calculation but only 1 for `file.read` (on some platforms),
//and we get undefined  behaviour when trying to read `length` characters.
file.open("test.txt", std::ifstream::in | std::ifstream::binary);
file.seekg(0, std::ios::end);
std::streampos length(file.tellg());
if (length) {
    file.seekg(0, std::ios::beg);
    vec.resize(static_cast<std::size_t>(length));
    file.read(&vec.front(), static_cast<std::size_t>(length));
}

显然,这不适用于超大型文件或对性能有严格要求的代码,但对于常规用途而言已经足够了。