在C++中将文件内容读入字符串

son*_*phi 76 c++ string file-io

可能重复:
在c ++中将文件粘贴到std :: string的最佳方法是什么?

在像Perl这样的脚本语言中,可以一次将文件读入变量.

    open(FILEHANDLE,$file);
    $content=<FILEHANDLE>;
Run Code Online (Sandbox Code Playgroud)

在C++中最有效的方法是什么?

Mai*_*ann 163

像这样:

#include <fstream>
#include <string>

int main(int argc, char** argv)
{

  std::ifstream ifs("myfile.txt");
  std::string content( (std::istreambuf_iterator<char>(ifs) ),
                       (std::istreambuf_iterator<char>()    ) );

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

该声明

  std::string content( (std::istreambuf_iterator<char>(ifs) ),
                       (std::istreambuf_iterator<char>()    ) );
Run Code Online (Sandbox Code Playgroud)

可以拆分成

std::string content;
content.assign( (std::istreambuf_iterator<char>(ifs) ),
                (std::istreambuf_iterator<char>()    ) );
Run Code Online (Sandbox Code Playgroud)

如果您只想覆盖现有std :: string变量的值,这将非常有用.

  • +1非常C++惯用语.在使用gcc 4.4的Linux中,生成的系统调用是高效的,文件一次读取8k. (6认同)
  • +1,但为什么迭代器*有*括在括号中?它们似乎无害,但没有它们就无法编译. (5认同)
  • Qix:这是一个名为Most Vexing Parse的"经典"c ++解析问题:http://en.wikipedia.org/wiki/Most_vexing_parse (5认同)
  • 如果文件大小已知,则可以在读取文件以分配空间之前调用std :: string :: reserve方法。这样可以加快执行速度。通过为字符串重新分配内存会浪费很多时间。 (2认同)

Cos*_*ert 39

最有效但不是C++的方式是:

   FILE* f = fopen(filename, "r");

   // Determine file size
   fseek(f, 0, SEEK_END);
   size_t size = ftell(f);

   char* where = new char[size];

   rewind(f);
   fread(where, sizeof(char), size, f);

   delete[] where;
Run Code Online (Sandbox Code Playgroud)

#编辑 - 2

刚刚测试了std::filebuf变体.看起来它可以被称为最好的C++的办法,即使它并不完全是C++的做法,但更多的是包装.无论如何,这里的代码块几乎和普通的C一样快.

   std::ifstream file(filename, std::ios::binary);
   std::streambuf* raw_buffer = file.rdbuf();

   char* block = new char[size];
   raw_buffer->sgetn(block, size);
   delete[] block;
Run Code Online (Sandbox Code Playgroud)

我在这里做了一个快速的基准测试,结果如下.在使用适当的(和)模式读取65536K二进制文件时进行测试.std::ios:binaryrb

[==========] Running 3 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 4 tests from IO
[ RUN      ] IO.C_Kotti
[       OK ] IO.C_Kotti (78 ms)
[ RUN      ] IO.CPP_Nikko
[       OK ] IO.CPP_Nikko (106 ms)
[ RUN      ] IO.CPP_Beckmann
[       OK ] IO.CPP_Beckmann (1891 ms)
[ RUN      ] IO.CPP_Neil
[       OK ] IO.CPP_Neil (234 ms)
[----------] 4 tests from IO (2309 ms total)

[----------] Global test environment tear-down
[==========] 4 tests from 1 test case ran. (2309 ms total)
[  PASSED  ] 4 tests.
Run Code Online (Sandbox Code Playgroud)

  • 你怎么在这里找到尺寸?! (4认同)
  • 不错的基准,我对这些数字并不感到惊讶.为了获得普通的ascii文件的最佳性能,使用旧的C io是最佳选择.C++流只是不匹配.但是,它们不容易出错.只要他们在分析时没有出现我更喜欢使用它们. (2认同)
  • 哇,这真的很酷.我不知道为什么,但起初我不相信你.看起来是结合`iostream`功能和原始C文件读取速度的最佳方式. (2认同)
  • @Constantino,你确定文件长度的方法不正确。尽管 fstat/rewing 组合有效,但正确的方法是填充 stat 结构并提取 st_size 成员。最好是安全起见。 (2认同)

Mar*_*ork 12

最有效的方法是创建一个正确大小的缓冲区,然后将文件读入缓冲区.

#include <fstream>
#include <vector>

int main()
{
    std::ifstream       file("Plop");
    if (file)
    {
        /*
         * Get the size of the file
         */
        file.seekg(0,std::ios::end);
        std::streampos          length = file.tellg();
        file.seekg(0,std::ios::beg);

        /*
         * Use a vector as the buffer.
         * It is exception safe and will be tidied up correctly.
         * This constructor creates a buffer of the correct length.
         * Because char is a POD data type it is not initialized.
         *
         * Then read the whole file into the buffer.
         */
        std::vector<char>       buffer(length);
        file.read(&buffer[0],length);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 此方法无法保证正常工作.`tellg`没有指定将偏移量以字节形式返回到文件中 - 它只是一个不透明的标记.[请参阅此答案](http://stackoverflow.com/a/22986486/1505939)以获取更详细的说明. (2认同)

Dra*_*ter 6

\0文本文件中应该没有.

#include<iostream>
#include<fstream>

using namespace std;

int main(){
  fstream f(FILENAME, fstream::in );
  string s;
  getline( f, s, '\0');

  cout << s << endl;
  f.close();
}
Run Code Online (Sandbox Code Playgroud)

  • 问题没有提到文本文件. (6认同)
  • -1这个例子只读了一行,我不得不怀疑调节. (3认同)
  • @piotr这个例子读取整个文本文件,经过测试. (2认同)