Effectuer des Opérations sur Fichiers en C++

C++Beginner
Pratiquer maintenant

Introduction

Dans ce laboratoire, vous apprendrez à effectuer diverses opérations sur les fichiers en C++. Le laboratoire couvre l'ouverture de fichiers en lecture et en écriture, l'écriture de données textuelles dans des fichiers, la lecture de données à partir de fichiers texte, la vérification de l'état d'ouverture du fichier, la gestion des erreurs de lecture/écriture de fichiers, le travail avec des fichiers binaires, le positionnement du pointeur de fichier et la fermeture des fichiers pour libérer les ressources. Vous acquerrez une expérience pratique dans l'utilisation des classes fondamentales de flux de fichiers ofstream et ifstream de la bibliothèque standard C++ pour interagir avec les fichiers. À la fin de ce laboratoire, vous aurez une solide compréhension de la gestion des fichiers dans la programmation C++.

Ouvrir des Fichiers avec ofstream et ifstream

Dans cette étape, vous apprendrez à ouvrir des fichiers en C++ en utilisant deux classes de flux de fichiers fondamentales : ofstream pour l'écriture de fichiers et ifstream pour la lecture de fichiers. Ces classes font partie de la bibliothèque standard C++ et fournissent des capacités essentielles de gestion de fichiers.

Tout d'abord, naviguez vers le répertoire du projet dans le terminal WebIDE :

cd ~/project

Créez un nouveau fichier C++ nommé file_operations.cpp :

touch file_operations.cpp

Ajoutez le code suivant au fichier file_operations.cpp :

#include <iostream>
#include <fstream>  // Inclure l'en-tête des flux de fichiers

int main() {
    // Ouverture d'un fichier pour l'écriture en utilisant ofstream
    std::ofstream outputFile("example.txt");

    // Vérifier si le fichier est ouvert avec succès
    if (outputFile.is_open()) {
        std::cout << "File opened for writing successfully!" << std::endl;
        outputFile.close();  // Fermer le fichier
    } else {
        std::cout << "Unable to open file for writing." << std::endl;
    }

    // Ouverture d'un fichier pour la lecture en utilisant ifstream
    std::ifstream inputFile("example.txt");

    // Vérifier si le fichier est ouvert avec succès
    if (inputFile.is_open()) {
        std::cout << "File opened for reading successfully!" << std::endl;
        inputFile.close();  // Fermer le fichier
    } else {
        std::cout << "Unable to open file for reading." << std::endl;
    }

    return 0;
}

Décortiquons les concepts clés :

  1. #include <fstream> : Inclut la bibliothèque de flux de fichiers
  2. std::ofstream : Flux de fichier de sortie (Output File Stream) pour l'écriture de fichiers
  3. std::ifstream : Flux de fichier d'entrée (Input File Stream) pour la lecture de fichiers
  4. is_open() : Vérifie si le fichier a été ouvert avec succès
  5. close() : Ferme le fichier après les opérations

Compilez le programme :

g++ file_operations.cpp -o file_operations

Exécutez l'exécutable :

./file_operations

Sortie exemple :

File opened for writing successfully!
File opened for reading successfully!

Quelques points importants concernant les flux de fichiers :

  • Vérifiez toujours si un fichier est ouvert avec succès avant d'effectuer des opérations
  • N'oubliez pas de fermer les fichiers après avoir terminé de les utiliser
  • ofstream est utilisé pour écrire dans les fichiers
  • ifstream est utilisé pour lire à partir des fichiers
  • Les deux classes font partie de l'en-tête <fstream>

Vous pouvez considérer les flux de fichiers comme l'ouverture et la fermeture de portes vers des fichiers. ofstream vous permet d'écrire dans une pièce, tandis que ifstream vous permet de lire ce qui s'y trouve.

Écrire des Données Texte dans les Fichiers

Dans cette étape, vous apprendrez à écrire des données textuelles dans des fichiers en utilisant la classe ofstream en C++. En vous basant sur l'étape précédente, vous explorerez différentes manières d'écrire des chaînes de caractères, des nombres et plusieurs lignes dans des fichiers.

Créez un nouveau fichier C++ nommé write_files.cpp :

touch ~/project/write_files.cpp

Ajoutez le code suivant au fichier write_files.cpp :

#include <iostream>
#include <fstream>
#include <string>

int main() {
    // Ouvrir un fichier pour l'écriture
    std::ofstream outputFile("student_data.txt");

    // Vérifier si le fichier est ouvert avec succès
    if (outputFile.is_open()) {
        // Écrire une seule chaîne de caractères
        outputFile << "John Doe" << std::endl;

        // Écrire plusieurs morceaux de données
        std::string name = "Alice Smith";
        int age = 22;
        double gpa = 3.75;
        outputFile << name << ", " << age << " years old, GPA: " << gpa << std::endl;

        // Écrire plusieurs lignes
        outputFile << "Computer Science Student" << std::endl;
        outputFile << "University of Programming" << std::endl;

        // Fermer le fichier
        outputFile.close();
        std::cout << "Data written to file successfully!" << std::endl;
    } else {
        std::cout << "Unable to open file for writing." << std::endl;
    }

    return 0;
}

Compilez le programme :

g++ write_files.cpp -o write_files

Exécutez l'exécutable :

./write_files

Sortie exemple :

Data written to file successfully!

Vérifiez le contenu du fichier :

cat student_data.txt

Contenu exemple du fichier :

John Doe
Alice Smith, 22 years old, GPA: 3.75
Computer Science Student
University of Programming

Points clés concernant l'écriture dans les fichiers :

  • Utilisez l'opérateur << pour écrire des données dans les fichiers
  • std::endl ajoute un saut de ligne
  • Peut écrire des chaînes de caractères, des nombres et des variables
  • Vérifiez toujours si le fichier est ouvert avant d'écrire
  • Fermez le fichier après les opérations d'écriture

Vous pouvez considérer l'écriture dans les fichiers comme écrire dans un cahier. L'ofstream est votre stylo, et le fichier est la page où vous enregistrez l'information.

Lire des Données à Partir de Fichiers Texte

Dans cette étape, vous apprendrez à lire des données à partir de fichiers texte en utilisant la classe ifstream en C++. En vous basant sur les étapes précédentes, vous explorerez différentes méthodes pour lire des lignes, des mots et des fichiers entiers.

Créez un nouveau fichier C++ nommé read_files.cpp :

touch ~/project/read_files.cpp

Ajoutez le code suivant au fichier read_files.cpp :

#include <iostream>
#include <fstream>
#include <string>

int main() {
    // Ouvrir le fichier créé à l'étape précédente
    std::ifstream inputFile("student_data.txt");

    // Vérifier si le fichier est ouvert avec succès
    if (inputFile.is_open()) {
        // Lire la ligne entière
        std::string line;
        std::cout << "Reading entire lines:" << std::endl;
        while (std::getline(inputFile, line)) {
            std::cout << line << std::endl;
        }

        // Réinitialiser le pointeur de fichier au début
        inputFile.clear();
        inputFile.seekg(0, std::ios::beg);

        // Lire les mots individuels
        std::cout << "\nReading individual words:" << std::endl;
        std::string word;
        while (inputFile >> word) {
            std::cout << word << " ";
        }
        std::cout << std::endl;

        // Fermer le fichier
        inputFile.close();
    } else {
        std::cout << "Unable to open file for reading." << std::endl;
    }

    return 0;
}

Compilez le programme :

g++ read_files.cpp -o read_files

Exécutez l'exécutable :

./read_files

Sortie exemple :

Reading entire lines:
John Doe
Alice Smith, 22 years old, GPA: 3.75
Computer Science Student
University of Programming

Reading individual words:
John Doe Alice Smith, 22 years old, GPA: 3.75 Computer Science Student University of Programming

Points clés concernant la lecture de fichiers :

  • Utilisez std::getline() pour lire des lignes entières
  • Utilisez l'opérateur >> pour lire des mots individuels
  • clear() et seekg() réinitialisent le pointeur de fichier
  • Vérifiez toujours si le fichier est ouvert avant de lire
  • Fermez le fichier après les opérations de lecture

Vous pouvez considérer la lecture de fichiers comme l'extraction d'informations d'un livre. L'ifstream est votre marque-page, vous aidant à naviguer dans le texte.

Vérifier l'État d'Ouverture du Fichier

Dans cette étape, vous apprendrez à vérifier l'état des opérations de fichier en C++ en utilisant diverses méthodes pour vérifier si les fichiers sont ouverts avec succès et prêts pour la lecture ou l'écriture.

Créez un nouveau fichier C++ nommé file_status.cpp :

touch ~/project/file_status.cpp

Ajoutez le code suivant au fichier file_status.cpp :

#include <iostream>
#include <fstream>
#include <string>

int main() {
    // Tentative d'ouverture d'un fichier existant pour la lecture
    std::ifstream inputFile("student_data.txt");

    // Méthode 1 : Utilisation de is_open() pour vérifier l'état du fichier
    if (inputFile.is_open()) {
        std::cout << "File opened successfully for reading." << std::endl;

        // Effectuer les opérations de lecture
        std::string line;
        while (std::getline(inputFile, line)) {
            std::cout << "Read line: " << line << std::endl;
        }

        inputFile.close();
    } else {
        std::cout << "Failed to open file for reading." << std::endl;
    }

    // Méthode 2 : Utilisation de good() pour vérifier l'état du fichier
    std::ofstream outputFile("test_status.txt");

    if (outputFile.good()) {
        std::cout << "File opened successfully for writing." << std::endl;
        outputFile << "Testing file status" << std::endl;

        // Vérifications d'état supplémentaires
        if (outputFile) {
            std::cout << "File is in a good state for writing." << std::endl;
        }

        outputFile.close();
    } else {
        std::cout << "Failed to open file for writing." << std::endl;
    }

    // Méthode 3 : Multiples méthodes de vérification d'état
    std::ifstream checkFile("non_existent_file.txt");

    std::cout << "File status checks:" << std::endl;
    std::cout << "is_open(): " << (checkFile.is_open() ? "True" : "False") << std::endl;
    std::cout << "good(): " << (checkFile.good() ? "True" : "False") << std::endl;
    std::cout << "fail(): " << (checkFile.fail() ? "True" : "False") << std::endl;

    return 0;
}

Compilez le programme :

g++ file_status.cpp -o file_status

Exécutez l'exécutable :

./file_status

Sortie exemple :

File opened successfully for reading.
Read line: John Doe
Read line: Alice Smith, 22 years old, GPA: 3.75
Read line: Computer Science Student
Read line: University of Programming
File opened successfully for writing.
File is in a good state for writing.
File status checks:
is_open(): False
good(): False
fail(): True

Points clés concernant la vérification de l'état des fichiers :

  • is_open() : Vérifie si le fichier a été ouvert avec succès
  • good() : Vérifie si aucune erreur ne s'est produite
  • fail() : Vérifie si une erreur s'est produite
  • Vérifiez toujours l'état du fichier avant d'effectuer des opérations
  • Différentes méthodes offrent diverses façons de vérifier l'état du fichier

Vous pouvez considérer les vérifications d'état de fichier comme une inspection de sécurité avant un voyage. Ces méthodes aident à garantir que vos opérations sur les fichiers sont sûres et réussies.

Gérer les Erreurs de Lecture/Écriture de Fichier

Dans cette étape, vous apprendrez à gérer les erreurs potentielles qui peuvent survenir lors des opérations de lecture et d'écriture de fichiers en C++. Comprendre la gestion des erreurs est crucial pour créer des programmes de manipulation de fichiers robustes.

Créez un nouveau fichier C++ nommé file_error_handling.cpp :

touch ~/project/file_error_handling.cpp

Ajoutez le code suivant au fichier file_error_handling.cpp :

#include <iostream>
#include <fstream>
#include <string>
#include <stdexcept>

void writeToFile(const std::string& filename) {
    std::ofstream outputFile(filename);

    // Vérifier si le fichier est ouvert
    if (!outputFile) {
        // Lever une exception si le fichier ne peut pas être ouvert
        throw std::runtime_error("Unable to open file for writing: " + filename);
    }

    try {
        // Tenter d'écrire des données
        outputFile << "Hello, Error Handling!" << std::endl;
        outputFile << "This is a sample text." << std::endl;

        // Simuler une erreur d'écriture (intentionnellement non recommandé)
        if (outputFile.bad()) {
            throw std::runtime_error("Write operation failed");
        }
    }
    catch (const std::exception& e) {
        std::cerr << "Error during writing: " << e.what() << std::endl;
    }

    outputFile.close();
}

void readFromFile(const std::string& filename) {
    std::ifstream inputFile(filename);
    std::string line;

    // Vérifier si le fichier est ouvert
    if (!inputFile) {
        // Lever une exception si le fichier ne peut pas être ouvert
        throw std::runtime_error("Unable to open file for reading: " + filename);
    }

    try {
        // Lire et afficher le contenu du fichier
        std::cout << "File contents:" << std::endl;
        while (std::getline(inputFile, line)) {
            std::cout << line << std::endl;
        }

        // Vérifier les erreurs de lecture
        if (inputFile.bad()) {
            throw std::runtime_error("Read operation encountered an error");
        }
    }
    catch (const std::exception& e) {
        std::cerr << "Error during reading: " << e.what() << std::endl;
    }

    inputFile.close();
}

int main() {
    try {
        // Écrire dans un fichier
        writeToFile("error_handling_example.txt");

        // Lire depuis le fichier
        readFromFile("error_handling_example.txt");

        // Tenter de lire à partir d'un fichier inexistant
        readFromFile("non_existent_file.txt");
    }
    catch (const std::exception& e) {
        std::cerr << "Main error: " << e.what() << std::endl;
        return 1;
    }

    return 0;
}

Compilez le programme :

g++ file_error_handling.cpp -o file_error_handling

Exécutez l'exécutable :

./file_error_handling

Sortie exemple :

File contents:
Hello, Error Handling!
This is a sample text.
Error during reading: Unable to open file for reading: non_existent_file.txt

Points clés concernant la gestion des erreurs de fichiers :

  • Utilisez des blocs try-catch pour gérer les exceptions potentielles
  • Vérifiez l'état du flux de fichier avant et après les opérations
  • Utilisez std::runtime_error pour lancer des messages d'erreur significatifs
  • Gérez différents types d'erreurs liées aux fichiers
  • Fournissez des messages d'erreur informatifs

Vous pouvez considérer la gestion des erreurs comme un filet de sécurité. Elle intercepte les problèmes potentiels et empêche votre programme de planter de manière inattendue.

Travailler avec des Fichiers Binaires en Utilisant fstream

Dans cette étape, vous apprendrez à travailler avec des fichiers binaires en utilisant la classe fstream en C++. Les fichiers binaires stockent les données dans leur format binaire brut, ce qui est différent des fichiers texte et utile pour stocker efficacement des données structurées.

Créez un nouveau fichier C++ nommé binary_files.cpp :

touch ~/project/binary_files.cpp

Ajoutez le code suivant au fichier binary_files.cpp :

#include <iostream>
#include <fstream>
#include <string>

// Structure simple pour démontrer l'écriture de fichiers binaires
struct Student {
    int id;
    char name[50];
    double gpa;
};

void writeBinaryFile() {
    std::fstream binaryFile("students.bin", std::ios::out | std::ios::binary);

    if (!binaryFile) {
        std::cerr << "Error opening file for writing!" << std::endl;
        return;
    }

    // Créer des enregistrements d'étudiants
    Student students[3] = {
        {1, "John Doe", 3.5},
        {2, "Alice Smith", 3.8},
        {3, "Bob Johnson", 3.2}
    };

    // Écrire la structure entière dans le fichier binaire
    binaryFile.write(reinterpret_cast<char*>(students), sizeof(students));

    binaryFile.close();
    std::cout << "Binary file written successfully!" << std::endl;
}

void readBinaryFile() {
    std::fstream binaryFile("students.bin", std::ios::in | std::ios::binary);

    if (!binaryFile) {
        std::cerr << "Error opening file for reading!" << std::endl;
        return;
    }

    Student students[3];

    // Lire la structure entière depuis le fichier binaire
    binaryFile.read(reinterpret_cast<char*>(students), sizeof(students));

    std::cout << "Student Records:" << std::endl;
    for (int i = 0; i < 3; ++i) {
        std::cout << "ID: " << students[i].id
                  << ", Name: " << students[i].name
                  << ", GPA: " << students[i].gpa << std::endl;
    }

    binaryFile.close();
}

int main() {
    // Écrire le fichier binaire
    writeBinaryFile();

    // Lire le fichier binaire
    readBinaryFile();

    return 0;
}

Compilez le programme :

g++ binary_files.cpp -o binary_files

Exécutez l'exécutable :

./binary_files

Sortie exemple :

Binary file written successfully!
Student Records:
ID: 1, Name: John Doe, GPA: 3.5
ID: 2, Name: Alice Smith, GPA: 3.8
ID: 3, Name: Bob Johnson, GPA: 3.2

Points clés concernant les fichiers binaires :

  • Utiliser le drapeau std::ios::binary pour le mode binaire
  • Méthodes write() et read() pour les données binaires
  • reinterpret_cast utilisé pour la conversion entre les types
  • Utile pour stocker efficacement des données structurées
  • Préserve la représentation binaire exacte des données

Vous pouvez considérer les fichiers binaires comme un plan précis. Ils stockent les données exactement telles qu'elles existent en mémoire, sans aucune conversion textuelle.

Positionner le Pointeur de Fichier avec seekg/seekp

Dans cette étape, vous apprendrez à manipuler les pointeurs de fichier en utilisant seekg() pour la lecture et seekp() pour l'écriture en C++. Ces méthodes vous permettent de naviguer et de modifier des positions spécifiques dans un fichier.

Créez un nouveau fichier C++ nommé file_pointer.cpp :

touch ~/project/file_pointer.cpp

Ajoutez le code suivant au fichier file_pointer.cpp :

#include <iostream>
#include <fstream>
#include <string>

void createSampleFile() {
    std::ofstream file("numbers.txt");
    for (int i = 1; i <= 10; ++i) {
        file << i << " ";
    }
    file.close();
}

void demonstrateSeekOperations() {
    // Ouvrir le fichier en mode lecture et écriture
    std::fstream file("numbers.txt", std::ios::in | std::ios::out);

    if (!file) {
        std::cerr << "Error opening file!" << std::endl;
        return;
    }

    // Opérations de lecture
    std::cout << "Reading operations:" << std::endl;

    // Se déplacer au 5ème octet (position du caractère)
    file.seekg(5);
    int value;
    file >> value;
    std::cout << "Value at 5th byte: " << value << std::endl;

    // Se déplacer au début du fichier
    file.seekg(0);
    file >> value;
    std::cout << "First value: " << value << std::endl;

    // Opérations d'écriture
    std::cout << "\nWriting operations:" << std::endl;

    // Se déplacer à une position spécifique et écrire
    file.seekp(0);
    file << "100 ";

    // Réinitialiser le pointeur de fichier et lire pour vérifier
    file.seekg(0);
    file >> value;
    std::cout << "Modified first value: " << value << std::endl;

    file.close();
}

int main() {
    // Créer un fichier d'exemple avec des nombres
    createSampleFile();

    // Démontrer les opérations de recherche (seek)
    demonstrateSeekOperations();

    return 0;
}

Compilez le programme :

g++ file_pointer.cpp -o file_pointer

Exécutez l'exécutable :

./file_pointer

Sortie exemple :

Reading operations:
Value at 5th byte: 4
First value: 1

Writing operations:
Modified first value: 100

Points clés concernant les pointeurs de fichier :

  • seekg() : Déplace le pointeur de lecture (get pointer)
  • seekp() : Déplace le pointeur d'écriture (put pointer)
  • Le premier argument est la position en octets (byte position)
  • Utile pour l'accès aléatoire dans les fichiers
  • Permet de naviguer vers des emplacements spécifiques

Vous pouvez considérer les pointeurs de fichier comme un curseur dans un éditeur de texte. seekg() et seekp() vous aident à déplacer ce curseur précisément là où vous le souhaitez.

Fermer les Fichiers et Libérer les Ressources

Dans cette étape, vous apprendrez l'importance de fermer correctement les fichiers et de gérer les ressources en C++ pour prévenir les fuites de mémoire et assurer une gestion efficace des fichiers. Vous explorerez différentes méthodes pour fermer les fichiers et utiliserez les principes RAII (Resource Acquisition Is Initialization - Acquisition de Ressource = Initialisation).

Créez un nouveau fichier C++ nommé file_resources.cpp :

touch ~/project/file_resources.cpp

Ajoutez le code suivant au fichier file_resources.cpp :

#include <iostream>
#include <fstream>
#include <string>
#include <memory>

// Fermeture manuelle de fichier
void manualFileHandling() {
    std::ofstream outputFile("manual_file.txt");

    if (outputFile.is_open()) {
        outputFile << "Manually managed file resource" << std::endl;

        // Fermeture explicite du fichier
        outputFile.close();

        std::cout << "File closed manually." << std::endl;
    }
}

// Gestion de fichier basée sur RAII utilisant unique_ptr
void raii_fileHandling() {
    try {
        // Utilisation de unique_ptr pour gérer la ressource fichier
        std::unique_ptr<std::ofstream> file(new std::ofstream("raii_file.txt"));

        if (file && file->is_open()) {
            *file << "RAII-managed file resource" << std::endl;
            std::cout << "RAII file handling successful." << std::endl;
        }
        // Le fichier est automatiquement fermé lorsque unique_ptr sort de portée
    }
    catch (const std::exception& e) {
        std::cerr << "Error in RAII file handling: " << e.what() << std::endl;
    }
}

// Gestion de fichier basée sur la portée (scope-based)
void scopeBasedFileHandling() {
    {
        // Le fichier sera automatiquement fermé lorsqu'il sortira de sa portée
        std::ofstream scopedFile("scoped_file.txt");

        if (scopedFile.is_open()) {
            scopedFile << "Scope-based file resource management" << std::endl;
            std::cout << "Scoped file handling successful." << std::endl;
        }
    } // Le fichier est automatiquement fermé ici
}

int main() {
    // Démontrer les différentes techniques de gestion des ressources de fichiers
    manualFileHandling();
    raii_fileHandling();
    scopeBasedFileHandling();

    return 0;
}

Compilez le programme :

g++ file_resources.cpp -o file_resources

Exécutez l'exécutable :

./file_resources

Sortie exemple :

File closed manually.
RAII file handling successful.
Scoped file handling successful.

Points clés concernant la fermeture des fichiers et la gestion des ressources :

  • Toujours fermer les fichiers après utilisation
  • Utiliser la méthode close() pour la fermeture manuelle
  • Tirer parti des principes RAII
  • Utiliser la gestion des ressources basée sur la portée (scope-based)
  • Prévenir les fuites de ressources
  • Gérer les exceptions lors des opérations sur les fichiers

Vous pouvez considérer les ressources de fichiers comme l'emprunt d'un livre à la bibliothèque. Retournez toujours le livre (fermez le fichier) lorsque vous avez terminé pour maintenir la bibliothèque (ressources système) organisée.

Résumé

Dans ce laboratoire, vous avez appris à ouvrir des fichiers en C++ en utilisant les classes ofstream et ifstream de la bibliothèque standard. Vous avez exploré le processus de vérification de l'état d'ouverture du fichier, d'écriture de données textuelles dans des fichiers et de lecture de données à partir de fichiers texte. De plus, vous avez acquis une compréhension de la gestion des erreurs de lecture/écriture de fichiers, du travail avec des fichiers binaires en utilisant fstream, du positionnement du pointeur de fichier avec seekg/seekp, et de la fermeture correcte des fichiers et de la libération des ressources. Ces opérations de fichier fondamentales sont essentielles pour gérer le stockage et la récupération des données dans les applications C++.