Question Lit tout le fichier ASCII en C ++ std :: string [duplicate]


Cette question a déjà une réponse ici:

Je dois lire un fichier entier en mémoire et le placer dans un C ++ std::string.

Si je devais le lire dans un char[], la réponse serait très simple:

std::ifstream t;
int length;
t.open("file.txt");      // open input file
t.seekg(0, std::ios::end);    // go to the end
length = t.tellg();           // report location (this is the length)
t.seekg(0, std::ios::beg);    // go back to the beginning
buffer = new char[length];    // allocate memory for a buffer of appropriate dimension
t.read(buffer, length);       // read the whole file into the buffer
t.close();                    // close file handle

// ... Do stuff with buffer here ...

Maintenant, je veux faire exactement la même chose, mais en utilisant un std::string au lieu d'un char[]. Je veux éviter les boucles, c'est-à-dire ne pas vouloir:

std::ifstream t;
t.open("file.txt");
std::string buffer;
std::string line;
while(t){
std::getline(t, line);
// ... Append line to buffer and go on
}
t.close()

Des idées?


495
2018-04-08 17:19


origine


Réponses:


Mettre à jour: Il s'avère que cette méthode, tout en suivant bien les idiomes du STL, est étonnamment inefficace! Ne faites pas cela avec de gros fichiers. (Voir: http://insanecoding.blogspot.com/2011/11/how-to-read-in-file-in-c.html)

Vous pouvez faire un streambuf iterator du fichier et initialiser la chaîne avec:

#include <string>
#include <fstream>
#include <streambuf>

std::ifstream t("file.txt");
std::string str((std::istreambuf_iterator<char>(t)),
                 std::istreambuf_iterator<char>());

Je ne sais pas où vous obtenez le t.open("file.txt", "r") syntaxe de. Autant que je sache, ce n'est pas une méthode std::ifstream a. On dirait que vous l'avez confondu avec C fopen.

Modifier: Notez également les parenthèses supplémentaires autour du premier argument du constructeur de chaîne. Ceux-ci sont essentiels. Ils empêchent le problème connu sous le nom de "analyse la plus vexante", qui dans ce cas ne vous donnera pas une erreur de compilation comme elle le fait habituellement, mais vous donnera des résultats intéressants (lire: faux).

En suivant le point de KeithB dans les commentaires, voici un moyen de le faire qui alloue toute la mémoire à l'avance (plutôt que de s'appuyer sur la réallocation automatique de la classe de chaînes):

#include <string>
#include <fstream>
#include <streambuf>

std::ifstream t("file.txt");
std::string str;

t.seekg(0, std::ios::end);   
str.reserve(t.tellg());
t.seekg(0, std::ios::beg);

str.assign((std::istreambuf_iterator<char>(t)),
            std::istreambuf_iterator<char>());

431
2018-04-08 17:23



Il y a plusieurs possibilités. J'adore utiliser un stringstream comme intermédiaire:

std::ifstream t("file.txt");
std::stringstream buffer;
buffer << t.rdbuf();

Maintenant, le contenu de "fichier.txt" est disponible dans une chaîne comme buffer.str().

Une autre possibilité (bien que je n'aime certainement pas aussi bien) ressemble beaucoup plus à votre original:

std::ifstream t("file.txt");
t.seekg(0, std::ios::end);
size_t size = t.tellg();
std::string buffer(size, ' ');
t.seekg(0);
t.read(&buffer[0], size); 

Officiellement, ceci n'est pas requis pour travailler sous le standard C ++ 98 ou 03 (la chaîne n'est pas nécessaire pour stocker les données de manière contiguë) mais en fait cela fonctionne avec toutes les implémentations connues, et C ++ 11 et ultérieur nécessitent un stockage contigu , donc c'est garanti de travailler avec eux.

Pour ce qui est de savoir pourquoi je n'aime pas la seconde aussi: premièrement, parce que c'est plus long et plus difficile à lire. Deuxièmement, comme il faut que vous initialisiez le contenu de la chaîne avec des données qui ne vous intéressent pas, alors écrivez immédiatement ces données (oui, l'heure d'initialisation est généralement triviale par rapport à la lecture, donc cela n'a pas d'importance , mais pour moi, ça fait quand même un peu faux). Troisièmement, dans un fichier texte, la position X dans le fichier ne signifie pas nécessairement que vous aurez lu X caractères pour atteindre ce point - il n'est pas nécessaire de prendre en compte des choses comme les traductions de ligne. Sur les systèmes réels qui font de telles traductions (par exemple, Windows) le formulaire traduit est plus court que celui du fichier (par exemple, "\ r \ n" dans le fichier devient "\ n" dans la chaîne traduite) donc tout ce que vous avez fait est réservé un peu d'espace supplémentaire que vous n'utilisez jamais. Encore une fois, ne cause pas vraiment de problème majeur mais se sent un peu mal de toute façon.


649
2018-04-08 17:53



Je pense que le meilleur moyen est d'utiliser un flux de chaînes. simple et rapide !!!

ifstream inFile;
inFile.open(inFileName);//open the input file

stringstream strStream;
strStream << inFile.rdbuf();//read the file
string str = strStream.str();//str holds the content of the file

cout << str << endl;//you can do anything with the string!!!

48
2017-11-12 06:08



Vous ne pouvez pas trouver ceci dans n'importe quel livre ou site mais j'ai découvert que cela fonctionne plutôt bien:

ifstream ifs ("filename.txt");
string s;
getline (ifs, s, (char) ifs.eof());

9
2017-11-10 16:48



Essayez l'une de ces deux méthodes:

string get_file_string(){
    std::ifstream ifs("path_to_file");
    return string((std::istreambuf_iterator<char>(ifs)),
                  (std::istreambuf_iterator<char>()));
}

string get_file_string2(){
    ifstream inFile;
    inFile.open("path_to_file");//open the input file

    stringstream strStream;
    strStream << inFile.rdbuf();//read the file
    return strStream.str();//str holds the content of the file
}

5
2018-02-05 12:50



J'ai trouvé une autre façon de travailler avec la plupart des istreams, y compris std :: cin!

std::string readFile()
{
stringstream str;
ifstream stream("Hello_World.txt");
if(stream.is_open())
{
    while(stream.peek() != EOF)
    {
        str << (char) stream.get();
    }
    stream.close();
    return str.str();
}
}

2
2017-08-20 05:23



Je pourrais le faire comme ceci:

void readfile(const std::string &filepath,std::string &buffer){
    std::ifstream fin(filepath.c_str());
    getline(fin, buffer, char(-1));
    fin.close();
}

Si c'est quelque chose à désapprouver, s'il vous plaît laissez-moi savoir pourquoi


1
2017-10-22 12:55