C++ 将文件加载到向量<;char>;

C++ 将文件加载到向量<;char>;,c++,iostream,C++,Iostream,我想将文本文件的内容加载到向量中(或者加载到任何字符输入迭代器中,如果可能的话)。当前我的代码如下所示: 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(

我想将文本文件的内容加载到
向量中(或者加载到任何字符输入迭代器中,如果可能的话)。当前我的代码如下所示:

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());
}
std::向量向量向量机;
std::ifstream文件(“test.txt”);
断言(file.is_open());
而(!(file.eof()| | file.fail()){
字符缓冲区[100];
文件读取(缓冲区,100);
insert(vec.end(),buffer,buffer+file.gcount());
}
我不喜欢手动使用缓冲区(为什么是100个字符?为什么不是200个,或者25个,或者其他什么?),也不喜欢使用大量的行。代码看起来非常难看,而且不是C++语言。有更直接的方法吗?

使用迭代器:

#include <iterator>

istream_iterator<char> data( file );
istream_iterator<char> end;
vec.insert( std::back_inserter(vec), data, end );
#包括
istream_迭代器数据(文件);
istream_迭代器端;
向量插入(标准::返回插入器(向量),数据,结束);

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

std::copy(std::istream_iterator<char>(file), std::istream_iterator<char>(), std::back_inserter(vec));
std::copy(std::istream_迭代器(文件),std::istream_迭代器(),std::back_插入器(vec));
可能你必须使用io操纵器来处理诸如换行符/空白之类的事情


编辑:如注释中所述,可能会影响性能。

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

#include <fstream>
#include <sstream>
#include <vector>
#include <string>

// for check:
#include <algorithm>
#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));
}
#包括
#包括
#包括
#包括
//检查:
#包括
#包括
#包括
int main(){
std::ifstream文件(“test.cc”);
std::ostringstream ss;

ss如果要避免逐字符读取:

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);
}

有很多很好的回复。谢谢大家!我决定使用的代码如下:

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));
}
std::向量向量向量机;
std::ifstream文件;
file.exceptions(
std::ifstream::badbit
|std::ifstream::failbit
|std::ifstream::eofbit);
//需要使用二进制模式;否则,CRLF行尾计数为2
//`长度`计算,但对于'file.read'(在某些平台上)仅为1,
//当我们试图读取'length'字符时,会出现未定义的行为。
open(“test.txt”,std::ifstream::in | std::ifstream::binary);
seekg(0,std::ios::end);
std::streampos长度(file.tellg());
if(长度){
seekg(0,std::ios::beg);
矢量调整大小(静态投影(长度));
file.read(&vec.front(),static_cast(length));
}

显然,这不适用于非常大的文件或性能关键型代码,但对于一般用途来说已经足够了。

看看这个响应:。它在中间状态下完全执行您想要的操作,甚至可以从字符串(或
vector
)中生成流@Diego-把这个写下来作为答案,我会接受的。这正是我想要的。完成了,尽管这可能会被认为是一个重复的问题?Re
assert(file.is_open());
:不要这样做!
assert
是一个可以扩展为零的宏(例如,释放模式)即使
assert
确实生成代码,它也没有帮助。丢失的文件是用户错误,而不是程序员错误。一般指导原则:使用
assert
来检测程序员错误。使用其他任何东西来检测用户错误。@David Hammen-我知道……目前这不完全是生产代码。我会修复代码但在问题中。@Diego:可能,我不知道std的实现细节,也无法测试它。此外,这不一定是个问题,但确实值得注意。进一步注意,如果性能要求不太严格,并且提问者真的只需要“任何字符输入迭代器”,则不需要容器。
std::istream_迭代器(文件),std::istream_迭代器()
已经是请求的InputIterator对。您的流将被缓冲,因此内核调用的开销应该很低。istream迭代器也可以在引擎盖下使用memcpy。它将有兴趣看到这与Eugene的解决方案之间的性能差异,但我认为差异不会很大。等等,我撒谎,你说得对,需要io操纵器来处理空白。所需的迭代器对是
std::istream_迭代器(文件>>std::noskipws),std::istream_迭代器()
。这不是一次读取一个字符并跳过空白吗?很好的解决方案,但这安全吗?@doron:“安全”从什么意义上讲?如果“安全”一词是关于不会使应用程序崩溃并将值正确复制到向量,我认为是的。但是在函数
file.read(&vec[0],fileSIZe)
执行之后。向量大小
vec.size()
仍然是零,vec.empty()是真的。我不确定这在你的应用程序中是否安全。事实上,在谷歌搜索之后,我发现了。答案在“坏主意”#2部分。基本上,它会导致未定义的行为。对于标准坚持者来说,重要的是要记住,没有人真正编写完全符合标准的代码。就像我怀疑如果
char
是9 bi,有多少代码会起作用一样所以有时候依靠事实上的标准是可以的。