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

可能的复制品:
在 c + + 中将文件转换成 std: : string 的最佳方法是什么?

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

    open(FILEHANDLE,$file);
$content=<FILEHANDLE>;

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

255377 次浏览

maybe not the most efficient, but reads data in one line:

#include<iostream>
#include<vector>
#include<iterator>


main(int argc,char *argv[]){
// read standard input into vector:
std::vector<char>v(std::istream_iterator<char>(std::cin),
std::istream_iterator<char>());
std::cout << "read " << v.size() << "chars\n";
}

Here's an iterator-based method.

ifstream file("file", ios::binary);
string fileStr;


istreambuf_iterator<char> inputIt(file), emptyInputIt
back_insert_iterator<string> stringInsert(fileStr);


copy(inputIt, emptyInputIt, stringInsert);

There should be no \0 in text files.

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

The most efficient, but not the C++ way would be:

   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;

#EDIT - 2

Just tested the std::filebuf variant also. Looks like it can be called the best C++ approach, even though it's not quite a C++ approach, but more a wrapper. Anyway, here is the chunk of code that works almost as fast as plain C does.

   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;

I've done a quick benchmark here and the results are following. Test was done on reading a 65536K binary file with appropriate (std::ios:binary and rb) modes.

[==========] 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.

Like this:

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

The statement

  std::string content( (std::istreambuf_iterator<char>(ifs) ),
(std::istreambuf_iterator<char>()    ) );

can be split into

std::string content;
content.assign( (std::istreambuf_iterator<char>(ifs) ),
(std::istreambuf_iterator<char>()    ) );

which is useful if you want to just overwrite the value of an existing std::string variable.

This depends on a lot of things, such as what is the size of the file, what is its type (text/binary) etc. Some time ago I benchmarked the following function against versions using streambuf iterators - it was about twice as fast:

unsigned int FileRead( std::istream & is, std::vector <char> & buff ) {
is.read( &buff[0], buff.size() );
return is.gcount();
}


void FileRead( std::ifstream & ifs, string & s ) {
const unsigned int BUFSIZE = 64 * 1024; // reasoable sized buffer
std::vector <char> buffer( BUFSIZE );


while( unsigned int n = FileRead( ifs, buffer ) ) {
s.append( &buffer[0], n );
}
}

The most efficient is to create a buffer of the correct size and then read the file into the buffer.

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