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