58 votes

Quelle est la façon la plus élégante pour lire un fichier texte avec le c++?

J'aimerais lire tout le contenu d'un fichier texte à un std::string objet avec c++.

Avec Python, je peux écrire:

text = open("text.txt", "rt").read()

Il est très simple et élégante. Je déteste les trucs moches, donc je voudrais savoir quelle est la façon la plus élégante pour lire un fichier texte avec le C++? Merci.

127voto

Milan Babuškov Points 20423

Il existe de nombreuses façons, à vous de choisir lequel est le plus élégant pour vous.

La lecture en char*:

ifstream file ("file.txt", ios::in|ios::binary|ios::ate);
if (file.is_open())
{
    file.seekg(0, ios::end);
    size = file.tellg();
    char *contents = new char [size];
    file.seekg (0, ios::beg);
    file.read (contents, size);
    file.close();
    //... do something with it
    delete [] contents;
}

En std::string:

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

Dans vector<char>:

std::ifstream in("file.txt");
std::vector<char> contents((std::istreambuf_iterator<char>(in)),
    std::istreambuf_iterator<char>());

En chaîne, à l'aide stringstream:

std::ifstream in("file.txt");
std::stringstream buffer;
buffer << in.rdbuf();
std::string contents(buffer.str());

file.txt est juste un exemple, tout fonctionne correctement pour les fichiers binaires ainsi, assurez-vous que vous utilisez ios::binary dans ifstream constructeur.

12voto

Konrad Rudolph Points 231505

Il y a un autre fil sur ce sujet.

Mon des solutions de ce thread (les deux one-liners):

Nice (voir Milan deuxième solution):

string str((istreambuf_iterator<char>(ifs)), istreambuf_iterator<char>());

et le jeûne:

string str(static_cast<stringstream const&>(stringstream() << ifs.rdbuf()).str());

4voto

sharkin Points 4935

Vous semblez parler de l'élégance définitive de la propriété de "peu de code". C'est bien sûr subjectif, dans une certaine mesure. Certains diront que d'omettre toute erreur de manipulation n'est pas très élégant. Certains diront que claire et compacte, code vous comprenez tout de suite est élégant.

Écrivez votre propre one-liner fonction/méthode qui lit le contenu du fichier, mais il est rigoureux et sûr sous la surface et vous aurez parcouru les deux aspects de l'élégance.

Tous les meilleurs

/Robert

1voto

Don Pedro Points 11

Mais attention, en c++une chaîne de caractères (ou plus concrète: STL-string) est un C-String est capable de tenir une chaîne de arbitraty longueur - bien sûr que non!

Jetez un oeil à la membre max_size() qui vous donne le nombre maximal de caractères une chaîne de caractères peut contenir. C'est une mise en œuvre réglés par le nombre et peuvent ne pas être transférables entre les différentes plates-formes. Visual Studio donne une valeur d'environ 4gigs pour les cordes, les autres risquent de vous donner uniquement de 64 ko et 64 bits-plates-formes, il peut vous donner quelque chose de vraiment énorme! Elle dépend et bien sûr, normalement, vous allez courir dans une bad_alloc-exception en raison de l'épuisement de la mémoire un long moment avant d'atteindre le 4gig limite...

BTW: max_size() est un membre d'une autre STL-conteneurs! Il vous donnera le nombre maximal d'éléments d'un certain type (pour lequel vous instanciée le conteneur) qui ce conteneur sera (théoriquement) être en mesure de tenir.

Donc, si vous êtes en train de lire à partir d'un fichier de unknow origine, vous devriez:
- Vérifier la taille et assurez-vous qu'il est plus petit que max_size()
- Intercepter et traiter les bad_alloc-exceptions

Et un autre point: Pourquoi êtes-vous désireux de lecture du fichier en une chaîne de caractères? Je m'attends à d'autres processus en incrémentale de l'analyse ou de quelque chose, non? Donc, au lieu de le lire en une chaîne de caractères peut ainsi lire dans un stringstream (qui est fondamentalement juste quelques sucre syntaxique pour une chaîne de caractères) et de faire le traitement. Mais alors vous pouvez faire le traitement directement à partir du fichier. Parce que si elle est correctement programmé les stringstream pourrait parfaitement être remplacé par un filestream, j'. e. par le fichier lui-même. Ou par tout autre flux d'entrée ainsi, ils partagent tous les mêmes membres et des opérateurs, et peut donc être facilement interchangeables!

Et pour le traitement lui-même: Il y a aussi beaucoup de choses que vous pouvez avoir automatisé par le compilateur! E. g. disons que vous voulez marquer la chaîne. Lors de la définition d'un modèle approprié les actions suivantes:
- Lecture à partir d'un fichier (ou d'une chaîne ou de tout autre flux d'entrée)
- La segmentation du contenu
- de pousser tout trouvé jetons dans une STL-conteneurs
- trier les jetons par ordre alphabétique
- eleminating le double des valeurs
pouvez tous(!!) être réalisée en une seule(!) ligne de C++-code (laissez de côté le modèle lui-même et de la gestion des erreurs)! Il suffit d'un seul appel de la fonction std::copy()! Juste google pour jeton "itérateur" et vous aurez une idée de ce que je veux dire. Donc, ce me semble, pour être encore plus "élégant" que de simplement lire à partir d'un fichier...

0voto

Shadow2531 Points 6726

J'aime Milan char*, mais avec un std::string.


#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
using namespace std;

string& getfile(const string& filename, string& buffer) {
    ifstream in(filename.c_str(), ios_base::binary | ios_base::ate);
    in.exceptions(ios_base::badbit | ios_base::failbit | ios_base::eofbit);
    buffer.resize(in.tellg());
    in.seekg(0, ios_base::beg);
    in.read(&buffer[0], buffer.size());
    return buffer;
}

int main(int argc, char* argv[]) {
    if (argc != 2) {
        cerr << "Usage: this_executable file_to_read\n";
        return EXIT_FAILURE;
    }
    string buffer;
    cout << getfile(argv[1], buffer).size() << "\n";
}

(avec ou sans le ios_base::binary, selon que vous voulez de nouvelles lignes traduit ou non. Vous pouvez également changer de getfile de simplement retourner une chaîne de sorte que vous n'avez pas à passer un tampon de chaîne. Ensuite, un test pour voir si le compilateur optimise la copie lors du retour.)

Cependant, cela peut paraître un peu mieux (et être un peu plus lent):


#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
using namespace std;

string getfile(const string& filename) {
    ifstream in(filename.c_str(), ios_base::binary);
    in.exceptions(ios_base::badbit | ios_base::failbit | ios_base::eofbit);
    return string(istreambuf_iterator<char>(in), istreambuf_iterator<char>());
}

int main(int argc, char* argv[]) {
    if (argc != 2) {
        cerr << "Usage: this_executable file_to_read\n";
        return EXIT_FAILURE;
    }
    cout << getfile(argv[1]).size() << "\n";
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X