web-dev-qa-db-fra.com

Comment lire le flux entier dans un std :: string?

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.


En fait, une référence const à une chaîne ferait également l'affaire, et cela pourrait faciliter les choses ...

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

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

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.

23
Joey Adams

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();
16
Matteo Italia

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) );
11
wheaties

Peut-être cette solution 1 ligne C++ 11:

std::vector<char> s{std::istreambuf_iterator<char>{in},{}};
0
user7223715

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);
0
wdavilaneto