Lire le fichier ligne par ligne

Le contenu de fichier.txt est:

5 3 6 4 7 1 10 5 11 6 12 3 12 4 

5 3 est une paire de coordonnées. Comment traiter ces données ligne par ligne en C ++?

Je peux obtenir la première ligne, mais comment puis-je obtenir la ligne suivante du fichier?

 ofstream myfile; myfile.open ("text.txt"); 

Tout d’abord, faites un ifstream :

 #include  std::ifstream infile("thefile.txt"); 

Les deux méthodes standard sont:

  1. Supposons que chaque ligne se compose de deux nombres et lit un jeton:

     int a, b; while (infile >> a >> b) { // process pair (a,b) } 
  2. Analyse basée sur les lignes, utilisant des stream de chaînes:

     #include  #include  std::ssortingng line; while (std::getline(infile, line)) { std::issortingngstream iss(line); int a, b; if (!(iss >> a >> b)) { break; } // error // process pair (a,b) } 

Vous ne devriez pas mélanger (1) et (2), car l’parsing basée sur des jetons ne gobe pas les nouvelles lignes, vous pouvez donc vous retrouver avec des lignes vides si vous utilisez getline() après que l’extraction basée sur les jetons vous fin d’une ligne déjà.

Utilisez ifstream pour lire les données d’un fichier:

 std::ifstream input( "filename.ext" ); 

Si vous avez vraiment besoin de lire ligne par ligne, faites ceci:

 for( std::ssortingng line; getline( input, line ); ) { ...for each line in input... } 

Mais vous avez probablement juste besoin d’extraire des paires de coordonnées:

 int x, y; input >> x >> y; 

Mettre à jour:

Dans votre code, vous utilisez ofstream myfile; , cependant, le o in ofstream représente la output . Si vous voulez lire le fichier (input), utilisez ifstream . Si vous voulez à la fois lire et écrire, utilisez fstream .

Puisque vos coordonnées sont regroupées en paires, pourquoi ne pas écrire une structure pour elles?

 struct CoordinatePair { int x; int y; }; 

Vous pouvez ensuite écrire un opérateur d’extraction surchargé pour istreams:

 std::istream& operator>>(std::istream& is, CoordinatePair& coordinates) { is >> coordinates.x >> coordinates.y; return is; } 

Et puis vous pouvez lire un fichier de coordonnées directement dans un vecteur comme celui-ci:

 #include  #include  #include  int main() { char filename[] = "coordinates.txt"; std::vector v; std::ifstream ifs(filename); if (ifs) { std::copy(std::istream_iterator(ifs), std::istream_iterator(), std::back_inserter(v)); } else { std::cerr << "Couldn't open " << filename << " for reading\n"; } // Now you can work with the contents of v } 

En étendant la réponse acceptée, si l’entrée est:

 1,NYC 2,ABQ ... 

vous pourrez toujours appliquer la même logique, comme ceci:

 #include  std::ifstream infile("thefile.txt"); if (infile.is_open()) { int number; std::ssortingng str; char c; while (infile >> number >> c >> str && c == ',') std::cout << number << " " << str << "\n"; } infile.close(); 

La lecture d’un fichier ligne par ligne en C ++ peut se faire de différentes manières.

[Fast] Boucle avec std :: getline ()

L’approche la plus simple consiste à ouvrir un std :: ifstream et une boucle en utilisant les appels std :: getline (). Le code est propre et facile à comprendre.

 #include  std::ifstream file(FILENAME); if (file.is_open()) { std::ssortingng line; while (getline(file, line)) { // using printf() in all tests for consistency printf("%s", line.c_str()); } file.close(); } 

[Rapide] Utiliser le fichier_description_source de Boost

Une autre possibilité est d’utiliser la bibliothèque Boost, mais le code devient un peu plus prolixe. La performance est assez similaire au code ci-dessus (Boucle avec std :: getline ()).

 #include  #include  #include  namespace io = boost::iostreams; void readLineByLineBoost() { int fdr = open(FILENAME, O_RDONLY); if (fdr >= 0) { io::file_descriptor_source fdDevice(fdr, io::file_descriptor_flags::close_handle); io::stream  in(fdDevice); if (fdDevice.is_open()) { std::ssortingng line; while (std::getline(in, line)) { // using printf() in all tests for consistency printf("%s", line.c_str()); } fdDevice.close(); } } } 

[Le plus rapide] Utiliser le code C

Si les performances sont essentielles pour votre logiciel, vous pouvez envisager d’utiliser le langage C. Ce code peut être 4 à 5 fois plus rapide que les versions C ++ ci-dessus, voir la référence ci-dessous

 FILE* fp = fopen(FILENAME, "r"); if (fp == NULL) exit(EXIT_FAILURE); char* line = NULL; size_t len = 0; while ((getline(&line, &len, fp)) != -1) { // using printf() in all tests for consistency printf("%s", line); } fclose(fp); if (line) free(line); 

Benchmark – Lequel est le plus rapide?

J’ai fait quelques tests de performance avec le code ci-dessus et les résultats sont intéressants. J’ai testé le code avec des fichiers ASCII contenant 100 000 lignes, 1 000 000 de lignes et 10 000 000 lignes de texte. Chaque ligne de texte contient 10 mots en moyenne. Le programme est compilé avec l’optimisation -O3 et sa sortie est transmise à /dev/null afin de supprimer la variable de temps de consignation de la mesure. Enfin, chaque élément de code enregistre chaque ligne avec la fonction printf() pour la cohérence.

Les résultats indiquent le temps (en ms) pris par chaque code pour lire les fichiers.

La différence de performance entre les deux approches C ++ est minime et ne devrait faire aucune différence dans la pratique. La performance du code C est ce qui rend la référence impressionnante et peut changer la donne en termes de vitesse.

  10K lines 100K lines 1000K lines Loop with std::getline() 105ms 894ms 9773ms Boost code 106ms 968ms 9561ms C code 23ms 243ms 2397ms 

entrer la description de l'image ici

Bien qu’il ne soit pas nécessaire de fermer le fichier manuellement, il est conseillé de le faire si la scope de la variable de fichier est plus grande:

  ifstream infile(szFilePath); for (ssortingng line = ""; getline(infile, line); ) { //do something with the line } if(infile.is_open()) infile.close(); 

avec des arguments de ligne de commande:

 #include  #include  #include  #include  #include "print.h" using namespace std; int main (int argc, char *argv[]) { vector list; ifstream in_stream; ssortingng line; in_stream.open(argv[1]); while(!in_stream.eof()) { in_stream >> line; list.push_back(line); } in_stream.close(); print(list); sort(list.begin(), list.end()); print(list); }