Fișiere Text în C++: “Memoria Permanentă” a Calculatorului

Bun venit la cea mai importantă lecție din viața unui program! Dacă până acum am lucrat cu date “pe viu” în memorie, acum învățăm cum să le salvăm și să le recuperăm, exact cum faci cu pozele pe telefon sau documentele pe calculator!

1. Ce sunt Fișierele Text? “Caietul de Notițe” al Programului

Analogie cu viața reală:

  • Memoria RAM = tabla cu cretă (se șterge când dai drumul la curent)
  • Fișierul text = caiet în care scrii (rămâne și după ce închizi calculatorul)

Cum gândește calculatorul:

Calculatorul vede: 
F I Ș I E R . T X T
↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
01000110 01001001 ...

Dar NOI îl vedem ca pe text normal!


2. Tipuri de Acces: “Cum Citești o Carte”

A. Acces Secvențial – “Cititul Pagină cu Pagină”

Imaginează-ți o casetă audio:

  • Pornesti de la început
  • Asculți piesa 1, apoi 2, apoi 3…
  • NU poți sări direct la piesa 3 fără să treci prin 1 și 2
#include <iostream>
#include <fstream>  // BIBLIOTECA MAGICĂ pentru fișiere!
using namespace std;

int main() {
    cout << "=== ACCES SECVENȚIAL ===\n";
    cout << "(ca o casetă audio)\n\n";

    // Scriere secvențială
    ofstream caseta_out("casetta.txt");

    caseta_out << "Piesa 1: Hello World\n";
    caseta_out << "Piesa 2: Salut Romania\n";
    caseta_out << "Piesa 3: La revedere\n";

    caseta_out.close();  // ÎNCHIDE întotdeauna caseta!

    // Citire secvențială
    ifstream caseta_in("casetta.txt");
    string linie;

    cout << "Ascult caseta de la început:\n";
    while(getline(caseta_in, linie)) {
        cout << "▶ " << linie << endl;
    }

    caseta_in.close();

    return 0;
}

B. Acces Aleator (Random Access) – “DVD-ul cu Butoane”

Imaginează-ți un DVD:

  • Poți sări la scena 5 direct
  • Poți derula înainte/înapoi
  • Ai butoane de control
#include <iostream>
#include <fstream>
using namespace std;

int main() {
    cout << "=== ACCES ALEATOR ===\n";
    cout << "(ca un DVD cu telecomanda)\n\n";

    // Creăm un "DVD" cu scene
    fstream dvd("filmul_meu.txt", ios::out);

    dvd << "Scena 1: Începutul\n";
    dvd << "Scena 2: Acțiunea\n";
    dvd << "Scena 3: Climaxul\n";
    dvd << "Scena 4: Sfârșitul\n";

    dvd.close();

    // Acum citim ca la DVD!
    fstream dvd_in("filmul_meu.txt", ios::in);

    // Sărim direct la scena 3
    // Găsim unde începe fiecare scenă...
    dvd_in.seekg(0, ios::end);  // Mergem la sfârșit
    int lungime = dvd_in.tellg();  // Aflăm lungimea totală

    cout << "Lungimea filmului: " << lungime << " caractere\n\n";

    // Mergem înapoi la începutul scenei 3
    dvd_in.seekg(30, ios::beg);  // Sărim la caracterul 30

    string scena3;
    getline(dvd_in, scena3);
    cout << "Am sărit la: " << scena3 << endl;

    dvd_in.close();

    return 0;
}

3. Biblioteca <fstream> – “Cutia cu Instrumente”

Cele 3 instrumente principale:

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

int main() {
    cout << "=== INSTRUMENTELE DIN <fstream> ===\n\n";

    // 1. OFSTREAM - "Scriitorul"
    // Doar SCRIE în fișier
    cout << "1. ofstream - SCRIITORUL:\n";
    ofstream scriitor("jurnal.txt");

    if(scriitor.is_open()) {  // VERIFICĂ dacă s-a deschis
        scriitor << "Azi am învățat C++\n";
        scriitor << "Este foarte interesant!\n";
        scriitor.close();
        cout << "   ✓ Am scris în jurnal\n";
    } else {
        cout << "   ✗ Nu pot deschide jurnalul\n";
    }

    // 2. IFSTREAM - "Cititorul"
    // Doar CITEȘTE din fișier
    cout << "\n2. ifstream - CITITORUL:\n";
    ifstream cititor("jurnal.txt");

    if(cititor.is_open()) {
        string linie;
        cout << "   Conținutul jurnalului:\n";

        while(getline(cititor, linie)) {
            cout << "   • " << linie << endl;
        }

        cititor.close();
    }

    // 3. FSTREAM - "Actorul Universal"
    // Poate atât CITI cât și SCRIE
    cout << "\n3. fstream - ACTORUL UNIVERSAL:\n";
    fstream universal("notite.txt", ios::out | ios::in | ios::app);

    if(universal.is_open()) {
        // Scrie ceva
        universal << "Notita 1: Cumpar lapte\n";

        // Citește ce am scris
        universal.seekg(0);  // Înapoi la început

        string continut;
        getline(universal, continut);
        cout << "   Am citit: " << continut << endl;

        universal.close();
    }

    return 0;
}

4. Moduri de Deschidere – “Cheile” pentru Fișiere

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

int main() {
    cout << "=== MODURILE DE DESCHIDERE ===\n";
    cout << "(diferite 'chei' pentru diferite uși)\n\n";

    // ios::out - "Scrie peste tot"
    // Dacă fișierul există, îl șterge și începe de la 0
    ofstream out("test_out.txt", ios::out);
    out << "Scriere cu ios::out\n";
    out.close();

    // ios::app - "Adaugă la sfârșit"
    // Ca să adaugi la un jurnal existent
    ofstream app("test_app.txt", ios::app);
    app << "Linie 1\n";
    app << "Linie 2\n";  // Se adaugă după Linie 1
    app.close();

    // ios::in - "Doar citire"
    // Doar citești, nu poți modifica
    ifstream in("test_app.txt", ios::in);
    // ... citește
    in.close();

    // ios::ate - "Sari la Sfârșit"
    // Deschide și sări direct la final
    fstream ate("test_app.txt", ios::ate | ios::in);
    ate << "Linie adăugată la sfârșit\n";
    ate.close();

    // ios::binary - "Mod binar"
    // Pentru imagini, sunete, executabile
    // (nu pentru text normal)

    cout << "Moduri comune combinate:\n";
    cout << "• ios::out | ios::app  - adaugă la sfârșit\n";
    cout << "• ios::in | ios::out   - citește și scrie\n";
    cout << "• ios::binary | ios::in - citire binară\n";

    return 0;
}

5. Cum Gândește Calculatorul cu Fișierele?

Imaginează-ți un cărăuș cu cărți:

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

int main() {
    cout << "=== CĂRĂUȘUL DE DATE ===\n\n";

    // 1. DESCHIDEREA - "Deschid ușa depozitului"
    fstream depozit("depozit.txt", ios::out);

    if(!depozit) {  // Verificare rapidă
        cout << "Ups! Nu pot deschide depozitul!\n";
        return 1;
    }

    // 2. SCRIEREA - "Pun cutii în depozit"
    cout << "Pun în depozit:\n";
    cout << " - Cutia 'Mere': 10kg\n";
    cout << " - Cutia 'Pere': 5kg\n";
    cout << " - Cutia 'Banane': 3kg\n\n";

    depozit << "Mere 10\n";
    depozit << "Pere 5\n";
    depozit << "Banane 3\n";

    // 3. ÎNCHIDEREA - "Închid ușa și încui"
    depozit.close();
    cout << "✓ Depozitul este închis și securizat!\n\n";

    // 4. REDESCHIDEREA - "Vin a doua zi la depozit"
    cout << "A doua zi...\n";
    depozit.open("depozit.txt", ios::in);

    // 5. CITIREA - "Verific ce am în depozit"
    cout << "Verific inventarul:\n";

    string produs;
    int cantitate;

    while(depozit >> produs >> cantitate) {
        cout << " • " << produs << ": " << cantitate << "kg\n";
    }

    depozit.close();

    // 6. ADAUGARE - "Mai aduc marfă"
    cout << "\nMai aduc mere...\n";

    ofstream adauga("depozit.txt", ios::app);  // APPEND!
    adauga << "Mere 5\n";  // +5kg mere
    adauga.close();

    cout << "✓ Am adăugat 5kg mere\n";

    return 0;
}

6. Lucrul cu Linii Complete

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

int main() {
    cout << "=== JURNALUL ELEVULUI ===\n\n";

    // Scriere cu getline
    ofstream jurnal("jurnal.txt");

    cout << "Scrie în jurnal (scrie 'stop' pe linie nouă pentru a încheia):\n";

    string intrare;
    while(true) {
        cout << "> ";
        getline(cin, intrare);

        if(intrare == "stop") {
            break;
        }

        jurnal << intrare << endl;
    }

    jurnal.close();

    // Citire cu getline
    cout << "\n--- CITIRE JURNAL ---\n";

    ifstream citire_jurnal("jurnal.txt");
    string linie;
    int numar_linie = 1;

    while(getline(citire_jurnal, linie)) {
        cout << numar_linie << ". " << linie << endl;
        numar_linie++;
    }

    citire_jurnal.close();

    return 0;
}

7. Verificări și Erori – “Sistemul de Alarmă”

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

int main() {
    cout << "=== SISTEMUL DE VERIFICARE ===\n\n";

    // Încerc să deschid un fișier care NU există
    ifstream fantoma("fisier_care_nu_exista.txt");

    cout << "1. Verific existența:\n";
    if(!fantoma) {
        cout << "   ✗ Fișierul nu există!\n";
        cout << "   (Calculatorul zice: 'Nu-l găsesc, boss!')\n";
    }

    cout << "\n2. Verific dacă e deschis:\n";
    if(!fantoma.is_open()) {
        cout << "   ✗ Nu e deschis (normal, nu există!)\n";
    }

    cout << "\n3. Verific sfârșitul fișierului (eof):\n";
    ifstream existent("existent.txt");

    if(existent) {
        string temp;
        while(!existent.eof()) {  // Cat timp NU am ajuns la End Of File
            getline(existent, temp);
            cout << "   Am citit: " << temp << endl;
        }
        cout << "   ✓ Am ajuns la sfârșitul fișierului\n";
    }

    cout << "\n4. Verificări rapide:\n";
    cout << "   • if(fisier)           - fișierul e bun\n";
    cout << "   • fisier.good()        - totul e în regulă\n";
    cout << "   • fisier.fail()        - ceva n-a mers bine\n";
    cout << "   • fisier.bad()         - eroare gravă\n";
    cout << "   • fisier.eof()         - am ajuns la sfârșit\n";

    return 0;
}

8. Exemplu Complex: “Agenda Telefonică”

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

struct Contact {
    string nume;
    string telefon;
    string email;
};

int main() {
    cout << "=== AGENDA TELEFONICĂ DIGITALĂ ===\n\n";

    // Meniu principal
    int optiune;

    do {
        cout << "\n=== MENIU ===\n";
        cout << "1. Adaugă contact\n";
        cout << "2. Vezi toate contactele\n";
        cout << "3. Caută contact\n";
        cout << "4. Ieșire\n";
        cout << "Alege: ";
        cin >> optiune;
        cin.ignore();  // Important!

        switch(optiune) {
            case 1: {
                // ADAUGARE CONTACT
                Contact nou;

                cout << "\n--- ADAUGĂ CONTACT ---\n";
                cout << "Nume: ";
                getline(cin, nou.nume);

                cout << "Telefon: ";
                getline(cin, nou.telefon);

                cout << "Email: ";
                getline(cin, nou.email);

                // Scrie în fișier (adaugă la sfârșit)
                ofstream agenda("agenda.txt", ios::app);

                if(agenda.is_open()) {
                    agenda << nou.nume << "," 
                           << nou.telefon << "," 
                           << nou.email << endl;

                    agenda.close();
                    cout << "✓ Contact salvat!\n";
                } else {
                    cout << "✗ Eroare la salvare!\n";
                }
                break;
            }

            case 2: {
                // AFIȘARE TOATE CONTACTELE
                cout << "\n--- LISTA CONTACTE ---\n";

                ifstream agenda("agenda.txt");

                if(agenda.is_open()) {
                    string linie;
                    int nr = 1;

                    while(getline(agenda, linie)) {
                        // Găsește virgulele
                        size_t virgula1 = linie.find(',');
                        size_t virgula2 = linie.find(',', virgula1 + 1);

                        if(virgula1 != string::npos && virgula2 != string::npos) {
                            string nume = linie.substr(0, virgula1);
                            string telefon = linie.substr(virgula1 + 1, virgula2 - virgula1 - 1);
                            string email = linie.substr(virgula2 + 1);

                            cout << nr << ". " << nume << endl;
                            cout << "   Tel: " << telefon << endl;
                            cout << "   Email: " << email << endl;
                            cout << endl;

                            nr++;
                        }
                    }

                    agenda.close();

                    if(nr == 1) {
                        cout << "Agenda este goală!\n";
                    }
                } else {
                    cout << "Nu am găsit agenda!\n";
                }
                break;
            }

            case 3: {
                // CĂUTARE CONTACT
                cout << "\n--- CĂUTARE CONTACT ---\n";
                cout << "Nume de căutat: ";

                string cauta;
                getline(cin, cauta);

                ifstream agenda("agenda.txt");
                bool gasit = false;

                if(agenda.is_open()) {
                    string linie;

                    while(getline(agenda, linie)) {
                        // Extrage numele (prima parte până la virgulă)
                        size_t virgula = linie.find(',');
                        string nume = linie.substr(0, virgula);

                        // Verifică dacă se potrivește
                        if(nume.find(cauta) != string::npos) {
                            cout << "\n✓ CONTACT GĂSIT:\n";
                            cout << "Nume: " << nume << endl;

                            // Extrage telefonul
                            size_t virgula2 = linie.find(',', virgula + 1);
                            string telefon = linie.substr(virgula + 1, virgula2 - virgula - 1);
                            cout << "Tel: " << telefon << endl;

                            // Extrage email
                            string email = linie.substr(virgula2 + 1);
                            cout << "Email: " << email << endl;

                            gasit = true;
                        }
                    }

                    agenda.close();

                    if(!gasit) {
                        cout << "✗ Nu am găsit contactul '" << cauta << "'\n";
                    }
                }
                break;
            }

            case 4:
                cout << "\nLa revedere! Agenda a fost salvată.\n";
                break;

            default:
                cout << "\n✗ Opțiune invalidă!\n";
        }

    } while(optiune != 4);

    return 0;
}

9. Reguli de Aur pentru Fișiere Text

REGULA 1: Închide întotdeauna fișierul!

// GREȘIT
ofstream fisier("test.txt");
fisier << "ceva";
// ... programul se încheie fără close()

// CORECT
ofstream fisier("test.txt");
fisier << "ceva";
fisier.close();  // ÎNCHIDE!

REGULA 2: Verifică dacă s-a deschis!

ofstream fisier("test.txt");

if(fisier.is_open()) {  // SAU: if(fisier)
    // ... operatii
} else {
    cout << "Eroare la deschidere!";
}

REGULA 3: Folosește ios::app pentru adăugare

// Dacă vrei să adaugi, NU să înlocuiești:
ofstream fisier("jurnal.txt", ios::app);  // APPEND!

REGULA 4: Șterge enter-ul cu cin.ignore()

int varsta;
string nume;

cout << "Varsta: ";
cin >> varsta;

cin.ignore();  // ȘTERGE ENTER-UL RĂMAS!

cout << "Nume: ";
getline(cin, nume);  // Acum merge bine!

10. Exercițiu Final: “Jocul Memoriei”

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

int main() {
    cout << "=== JOCUL MEMORIEI ===\n";
    cout << "Scrie ce vrei, iar calculatorul își va aminti!\n\n";

    // Deschide sau creează fișierul
    fstream memoria("memorie.txt", ios::in | ios::out | ios::app);

    if(!memoria.is_open()) {
        // Dacă nu există, îl creează
        memoria.open("memorie.txt", ios::out);
        memoria << "=== JOCUL MEMORIEI ===\n";
        memoria.close();

        memoria.open("memorie.txt", ios::in | ios::out | ios::app);
    }

    // Citește ce era deja
    cout << "AMINTIRILE ANTERIOARE:\n";
    cout << "----------------------\n";

    memoria.seekg(0);  // Mergi la început
    string linie;

    while(getline(memoria, linie)) {
        cout << linie << endl;
    }

    // Adaugă amintire nouă
    cout << "\n--- ADAUGĂ O AMINTIRE ---\n";
    cout << "Scrie ceva (scrie 'gata' pentru a încheia):\n";

    string amintire;
    time_t acum = time(0);
    char* data = ctime(&acum);

    memoria << "\n[" << data << "]\n";

    while(true) {
        cout << "> ";
        getline(cin, amintire);

        if(amintire == "gata") {
            break;
        }

        memoria << "- " << amintire << endl;
    }

    memoria << "----------------------\n";

    memoria.close();

    cout << "\n✓ Am salvat amintirea!\n";
    cout << "Data viitoare când vei rula programul,\n";
    cout << "vei vedea și amintirile vechi!\n";

    return 0;
}

CONCLUZIE: De ce sunt importante fișierele?

  1. Persistență – Datele rămân și după ce închizi programul
  2. Partajare – Poți trimite fișierul altcuiva
  3. Backup – Poți salva progresul în jocuri/programe
  4. Logging – Programele “țin jurnal” cu ce fac

Gândiți-vă la fișiere ca la:

  • Jurnal personal pentru program
  • Cutie de valori pentru date importante
  • Memorie externă pentru calculator

Ultimul sfat:

// Întotdeauna tratează fișierele cu grijă!
// E ca și cum ai avea grijă de un caiet prețios.

// Verifică, închide, și fii atent la erori!
// Happy coding! 📁✨

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *