Come leggere l’intero stream in una stringa std ::?

Sto cercando di leggere un intero stream (più righe) in una stringa.

Sto usando questo codice, e funziona, ma sta offendendo il mio senso dello stile … Sicuramente c’è un modo più semplice? Forse usando i giri di strings?

void Obj::loadFromStream(std::istream & stream) { std::string s; std::streampos p = stream.tellg(); // remember where we are stream.seekg(0, std::ios_base::end); // go to the end std::streamoff sz = stream.tellg() - p; // work out the size stream.seekg(p); // restore the position s.resize(sz); // resize the string stream.read(&s[0], sz); // and finally, read in the data. 

In realtà, farebbe anche un riferimento const a una stringa, e questo potrebbe rendere le cose più facili …

 const std::string &s(... a miracle occurs here...) 

Che ne dite di

 std::istreambuf_iterator eos; std::string s(std::istreambuf_iterator(stream), eos); 

(potrebbe essere un one-liner se non per MVP)

modifica post-2011, questo approccio è ora scritto

 std::string s(std::istreambuf_iterator(stream), {}); 

Sono in ritardo per la festa, ma qui è una soluzione abbastanza efficiente:

 std::string gulp(std::istream &in) { std::string ret; char buffer[4096]; while (in.read(buffer, sizeof(buffer))) ret.append(buffer, sizeof(buffer)); ret.append(buffer, in.gcount()); return ret; } 

Ho fatto un po ‘di benchmark, e si scopre che la tecnica std::istreambuf_iterator ( usata dalla risposta accettata ) è in realtà molto più lenta. In gcc 4.4.5 con -O3 , si tratta di una differenza di 4,5 volte sulla mia macchina e il divario si allarga con impostazioni di ottimizzazione inferiori.

Potresti farlo

 std::string s; std::ostringstream os; os< 

ma non so se è più efficiente.

Versione alternativa:

 std::string s; std::ostringstream os; stream>>os.rdbuf(); s=os.str(); 

Puoi provare a usare qualcosa dagli algoritmi. Devo prepararmi per il lavoro, ma qui c’è un attacco rapido alle cose (deve esserci un modo migliore):

 copy( istreambuf_iterator(stream), istreambuf_iterator(), back_inserter(s) ); 

Bene, se stai cercando un modo semplice e ‘leggibile’ per farlo. Consiglio di aggiungere / utilizzare un framework di alto livello sul tuo progetto. Per questo uso sempre Poco e Boost su tutti i miei progetti. In questo caso, con Poco:

  string text; FileStream fstream(TEXT_FILE_PATH); StreamCopier::copyToString(fstream, text); 

Forse questa soluzione C ++ 11 a 1 riga:

 std::vector s{std::istreambuf_iterator{in},{}};