Mogelijk duplicaat:
Wat is het beste manier om een bestand in een std::string in c++ te slurpen?
In scripttalen zoals Perl is het mogelijk om een bestand in één keer in een variabele te lezen.
open(FILEHANDLE,$file);
$content=<FILEHANDLE>;
Wat zou de meest efficiënte manier zijn om dit in C++ te doen?
Antwoord 1, autoriteit 100%
Zoals dit:
#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;
}
De verklaring
std::string content( (std::istreambuf_iterator<char>(ifs) ),
(std::istreambuf_iterator<char>() ) );
kan worden opgesplitst in
std::string content;
content.assign( (std::istreambuf_iterator<char>(ifs) ),
(std::istreambuf_iterator<char>() ) );
wat handig is als je gewoon de waarde van een bestaande std::string variabele wilt overschrijven.
Antwoord 2, autoriteit 20%
De meest efficiënte, maar niet de C++-manier zou zijn:
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;
#
BEWERKEN – 2
Zojuist ook de variant std::filebuf
getest. Het lijkt erop dat het de beste C++-benadering kan worden genoemd, ook al is het niet echt een C++-benadering, maar meer een wrapper. Hoe dan ook, hier is het stukje code dat bijna net zo snel werkt als gewone 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;
Ik heb hier een snelle benchmark gedaan en de resultaten volgen. Er is een test gedaan bij het lezen van een 65536Kbinair bestand met de juiste (std::ios:binary
en rb
) modi.
[==========] 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.
Antwoord 3, autoriteit 6%
Het meest efficiënt is om een buffer van de juiste grootte te maken en het bestand vervolgens in de buffer te lezen.
#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);
}
}