Pourquoi la simple lecture d'un fichier en C++ casse le code même chez les expérimentés ?
\n\nImaginez la situation : vous écrivez un analyseur de fichiers de configuration, de logs ou CSV. Tout semble élémentaire — ouvrir le fichier, lire ligne par ligne, traiter. Mais en réalité, sur Stack Overflow, la question "Read file line by line using ifstream in C++" recueille des milliers de vues et des centaines de commentaires. Pourquoi ? Parce que le diable, comme toujours, se cache dans les détails.
\n\nDans cet article, nous ne montrerons pas seulement comment lire correctement un fichier ligne par ligne. Nous analyserons les 5 erreurs les plus fréquentes et dangereuses qui transforment un code fonctionnel en un tas de bugs. Vous découvrirez pourquoi while (!file.eof()) est un mal, comment ne pas perdre la dernière ligne et que faire avec les fichiers binaires. C'est parti !
Syntaxe de base : comment ouvrir un fichier et lire une ligne
\n\nCommençons par les bases. La classe std::ifstream (input file stream) est votre outil principal pour lire des fichiers. Voici un exemple fonctionnel minimal :
#include <iostream>\n#include <fstream>\n#include <string>\n\nint main() {\n std::ifstream file("example.txt");\n std::string line;\n\n if (file.is_open()) {\n while (std::getline(file, line)) {\n std::cout << line << std::endl;\n }\n file.close();\n } else {\n std::cerr << "Erreur d'ouverture du fichier !" << std::endl;\n }\n return 0;\n}\n\nIl semble que rien ne puisse mal tourner ? Et pourtant.
\n\nErreur n°1 : Utilisation de while (!file.eof())
\n\nC'est sans doute le piège le plus courant pour les débutants. Cela semble logique : "tant que ce n'est pas la fin du fichier — lis". Mais voici le problème :
\n\n- \n
eof()retournetrueseulement après une tentative de lecture échouée. \n - La boucle s'exécutera une itération de plus que nécessaire. \n
- La dernière ligne sera traitée deux fois ou vous obtiendrez des données erronées. \n
Exemple-catastrophe :
\n\nstd::ifstream file("data.txt");\nstd::string line;\n\nwhile (!file.eof()) { // NE FAITES JAMAIS CELA !\n std::getline(file, line);\n std::cout << line << std::endl; // La dernière ligne s'affichera deux fois\n}\n\nSolution correcte : utilisez std::getline dans la condition de la boucle, comme dans le premier exemple. Il retourne le flux lui-même, qui est converti en bool : true si la lecture est réussie, et false en cas d'erreur ou de fin de fichier.
Erreur n°2 : Ignorer la vérification d'ouverture du fichier
\n\nCela semble évident, mais des milliers de lignes de code sur GitHub plantent avec une erreur de segmentation à cause de cela. Si le fichier n'existe pas ou si vous n'avez pas les droits de lecture, ifstream ne lèvera pas d'exception — il sera simplement dans un état "cassé".
Incorrect :
\n\nstd::ifstream file("nonexistent.txt");\nstd::string line;\nwhile (std::getline(file, line)) { // Oups ! Le fichier ne s'est pas ouvert\n // Ce code ne s'exécutera jamais\n}\n\nLe problème est que vous ne saurez pas qu'il y a une erreur. Les données seront vides et la logique du programme sera brisée.
\n\nCorrect :
\n\nstd::ifstream file("data.txt");\nif (!file) {\n std::cerr << "Impossible d'ouvrir le fichier !" << std::endl;\n return 1;\n}\n// Ensuite, la lecture\n\nUtilisez if (!file) ou if (!file.is_open()) — il n'y a pas de différence, les deux vérifient l'état du flux.
Erreur n°3 : Oublier les espaces et les séparateurs
\n\nL'opérateur >> (extraction) lit jusqu'au premier espace. Si vous l'utilisez à la place de std::getline, vous risquez d'obtenir autre chose que ce que vous attendiez.
Exemple : le fichier contient la ligne "Hello World".
std::string word;\nfile >> word; // Lira seulement "Hello"\n// word == "Hello"