J'essaie de lire un flux entier (plusieurs lignes) dans une chaîne.
J'utilise ce code, et ça marche, mais ça choque mon sens du style ... Il y a sûrement un moyen plus facile? Peut-être en utilisant stringstreams?
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.
const
à une chaîne ferait également l'affaire, et cela pourrait faciliter les choses ...const std::string &s(... a miracle occurs here...)
Que diriez-vous
std::istreambuf_iterator<char> eos;
std::string s(std::istreambuf_iterator<char>(stream), eos);
(pourrait être un one-liner si pas pour MVP)
édition post-2011, cette approche est maintenant orthographiée
std::string s(std::istreambuf_iterator<char>(stream), {});
Je suis en retard à la fête, mais voici une solution assez efficace:
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;
}
J'ai fait quelques analyses comparatives et il s'est avéré que la technique std::istreambuf_iterator
( utilisée par la réponse acceptée ) est en réalité beaucoup plus lente. Sur gcc 4.4.5 avec -O3
, il y a une différence de 4,5 x sur ma machine, et l'écart s’élargit avec des paramètres d’optimisation inférieurs.
Vous pourriez faire
std::string s;
std::ostringstream os;
os<<stream.rdbuf();
s=os.str();
mais je ne sais pas si c'est plus efficace.
Version alternative:
std::string s;
std::ostringstream os;
stream>>os.rdbuf();
s=os.str();
Vous pouvez essayer d'utiliser quelque chose d'algorithmes. Je dois me préparer pour le travail, mais voici un coup d’œil rapide (il doit y avoir un meilleur moyen):
copy( istreambuf_iterator<char>(stream), istreambuf_iterator<char>(), back_inserter(s) );
Peut-être cette solution 1 ligne C++ 11:
std::vector<char> s{std::istreambuf_iterator<char>{in},{}};
Eh bien, si vous recherchez un moyen simple et "lisible" de le faire. Je recommanderais d'ajouter/d'utiliser un cadre de haut niveau pour votre projet. Pour cela, j'utilise toujours Poco et Boost sur tous mes projets. Dans ce cas, avec Poco:
string text;
FileStream fstream(TEXT_FILE_PATH);
StreamCopier::copyToString(fstream, text);