¿Cómo leer todo el flujo en std :: string?

Intento leer una secuencia completa (varias líneas) en una cadena.

Estoy usando este código, y funciona, pero está ofendendo mi sentido del estilo … ¿Seguro que hay una manera más fácil? Tal vez usando cadenas de caracteres?

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); // restre the position s.resize(sz); // resize the string stream.read(&s[0], sz); // and finally, read in the data. 

En realidad, una referencia const a una cadena también lo haría, y eso puede facilitar las cosas …

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

Qué tal si

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

(podría ser de una sola línea si no fuera por MVP)

edición posterior a 2011, este enfoque ahora se deletrea

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

Llego tarde a la fiesta, pero aquí hay una solución bastante eficiente:

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

Hice algunos benchmarking, y resulta que la técnica std::istreambuf_iterator ( utilizada por la respuesta aceptada ) es en realidad mucho más lenta. En gcc 4.4.5 con -O3 , se trata de una diferencia de 4.5x en mi máquina, y la brecha se hace más amplia con configuraciones de optimización más bajas.

Podrías hacerlo

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

pero no sé si es más eficiente.

Versión alternativa:

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

Puedes intentar usar algo de los algoritmos. Tengo que prepararme para el trabajo, pero aquí hay una puñalada muy rápida (tiene que haber una mejor manera):

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

Bueno, si buscas una forma simple y ‘legible’ de hacerlo. Recomiendo añadir / utilizar un marco de alto nivel en su proyecto. Para eso, siempre uso Poco y Boost en todos mis proyectos. En este caso, con Poco:

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

Quizás esta solución de 1 línea C ++ 11:

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