Biblioteca
Tutora
BibliotecaInformatică și TIC › clasa a XII-a

Fișiere

Prelucrarea datelor stocate în fișiere text și binare utilizând tehnici specifice limbajului de programare studiat.

Bacalaureat

Ce este un fișier și de ce diferă de memoria internă

Un fișier este o colecție de date memorată pe un suport extern, identificată printr-un nume și gestionată de sistemul de operare. Diferența esențială față de vectori sau matrice, cerută frecvent la teorie, este persistența: datele din memoria internă dispar la terminarea programului, cele din fișier rămân.

A doua diferență e la fel de importantă practic: dimensiunea unui fișier nu trebuie declarată dinainte. Un vector are un număr maxim de elemente fixat la compilare; într-un fișier poți scrie oricâte înregistrări încape pe disc. De aceea problemele de BAC care spun „numărul de valori nu este cunoscut” se rezolvă citind din fișier până la epuizare, nu alocând un vector uriaș.

Clasificarea de bază, după modul de reprezentare a datelor:

După modul de acces:

Orice prelucrare respectă aceeași succesiune obligatorie: deschidere, prelucrare, închidere. Închiderea nu e o formalitate — la scriere ea golește zona tampon (bufferul) pe disc; un program care se termină fără să închidă fișierul poate lăsa ultimele date nescrise.

Fișiere text: citire și scriere

În C++ lucrul cu fișiere se face prin fluxuri (stream-uri): ifstream pentru citire, ofstream pentru scriere, fstream pentru ambele. Fluxul se leagă de fișier prin constructor sau prin metoda open, iar la final se apelează close.

Reguli de deschidere care se transformă direct în puncte pierdute:

Citirea se face cu operatorul de extragere pentru valori separate prin spații sau linii noi, cu getline pentru o linie întreagă (inclusiv spațiile din interiorul ei) și cu metoda get pentru un singur caracter. Amestecarea lor cere atenție: după o citire cu operatorul de extragere, în flux rămâne marcajul de sfârșit de linie, iar un getline imediat următor va citi un șir vid — este cea mai frecventă eroare de execuție la subiectele cu fișiere.

Oprirea citirii se face pe condiția de succes a operației, nu pe funcția de test a sfârșitului de fișier apelată înainte de citire. Motivul: indicatorul de sfârșit de fișier se activează abia după o încercare de citire eșuată, deci un ciclu care testează sfârșitul înainte de citire prelucrează ultima valoare de două ori. Forma corectă pune citirea chiar în condiția ciclului.

La scriere, valorile trebuie separate explicit prin spațiu sau prin trecere la linie nouă; altfel 12 și 5 se lipesc în fișier și devin la recitire numărul 125.

Actualizarea unui fișier text

Întrebarea de teorie care sperie: cum modifici o valoare dintr-un fișier text? Răspunsul corect este că, în general, nu poți modifica pe loc. Într-un fișier text liniile au lungimi diferite, iar dacă înlocuiești un număr de două cifre cu unul de trei, nu ai unde să pui cifra suplimentară — ai suprascrie caracterele următoare.

Tehnica standard de actualizare, cerută la subiecte, are trei pași:

Aceeași schemă rezolvă toate operațiile de întreținere: ștergerea unei înregistrări (nu o copiezi), inserarea (o scrii înainte de cea în fața căreia trebuie să apară), modificarea (o scrii cu valorile noi).

Există și varianta „încarcă tot în memorie”: se citește fișierul într-un vector, se modifică vectorul, apoi se rescrie fișierul de la zero. Este mai simplă și perfect acceptabilă la BAC dacă enunțul garantează un număr maxim de valori, dar cade exact acolo unde fișierele își arată forța — la volume care nu încap în memorie.

Excepția de la regulă merită reținută: la un fișier binar cu înregistrări de lungime fixă, actualizarea pe loc este posibilă, pentru că înregistrarea nouă ocupă exact spațiul celei vechi.

Fișiere binare și prelucrarea înregistrărilor

Un fișier binar conține imaginea exactă a datelor din memorie. Se deschide cu modul binary adăugat la modul de acces, iar transferul nu se mai face cu operatorii de citire/scriere formatată, ci cu metodele read și write, care primesc adresa zonei de memorie și numărul de octeți transferați.

Avantajele față de text, așa cum se cer la comparație:

Dezavantajele: fișierul nu este lizibil într-un editor de text și nu este portabil între arhitecturi care reprezintă diferit numerele.

O înregistrare este unitatea logică de informație, de regulă o structură cu mai multe câmpuri — de exemplu un elev cu nume, clasă și medie. Fișierul binar de înregistrări se prelucrează cel mai natural: se citește câte o structură întreagă dintr-o singură operație, se prelucrează, se trece la următoarea.

Atenție la capcana cea mai serioasă: o structură care conține pointeri (de exemplu un șir alocat dinamic) nu se poate salva direct în fișier binar. S-ar scrie adresa, nu conținutul, iar la o rulare ulterioară adresa nu mai înseamnă nimic. Se salvează doar structuri cu câmpuri de dimensiune fixă, tablourile de caractere fiind soluția uzuală în locul șirurilor dinamice.

Acces secvențial și acces direct; poziționarea în fișier

Fiecare flux deschis are un indicator de poziție — un „cursor” care arată de unde se va face următoarea operație. La accesul secvențial, cursorul înaintează singur, cu numărul de octeți citiți sau scriși; pentru a ajunge la a n-a componentă trebuie citite toate cele n-1 dinaintea ei.

La accesul direct, cursorul se mută explicit, cu metodele de poziționare: seekg pentru fluxul de intrare și seekp pentru cel de ieșire. Poziția se dă în octeți, măsurați față de un reper: începutul fișierului, poziția curentă sau sfârșitul fișierului. Poziția curentă se află cu tellg, respectiv tellp.

Formula cheie, care apare în aproape orice problemă de acces direct: dacă înregistrările au toate dimensiunea d, atunci înregistrarea cu numărul de ordine k, numerotată de la 0, începe la octetul *k d. Din același raționament rezultă și numărul total de înregistrări: te poziționezi la sfârșitul fișierului, citești poziția (adică dimensiunea în octeți) și o împarți la d**.

Greșeli de punctaj legate de poziționare:

Un fișier binar cu înregistrări fixe permite deci ceea ce un fișier text nu permite: citirea, modificarea și rescrierea unei singure înregistrări, fără a atinge restul fișierului.

De reținut

fișier
colecție de date memorată pe un suport extern, identificată prin nume, cu dimensiune nedeclarată în prealabil și cu date care persistă după terminarea programului
fișier text
fișier în care informația este memorată ca succesiune de caractere organizată pe linii, lizibil într-un editor de text și accesibil practic doar secvențial
fișier binar
fișier în care datele sunt memorate în reprezentarea lor internă din memorie, mai compact și mai rapid, dar nelizibil într-un editor de text
acces secvențial
mod de acces în care ajungerea la componenta k presupune parcurgerea tuturor componentelor care o preced
acces direct
mod de acces în care se poate sări imediat la o componentă, calculându-i poziția; posibil doar la fișiere cu înregistrări de dimensiune fixă
înregistrare
unitatea logică de informație dintr-un fișier, de regulă o structură cu mai multe câmpuri, prelucrată ca un tot unitar
indicator de poziție
cursorul intern al fluxului care arată octetul de la care se face următoarea operație de citire sau de scriere
actualizare prin fișier temporar
tehnica de modificare a unui fișier text prin copierea lui, cu schimbările dorite, într-un fișier nou, urmată de ștergerea originalului și redenumirea copiei
închiderea fișierului
operația care eliberează resursele și golește zona tampon pe disc, garantând scrierea efectivă a ultimelor date

Greșeli frecvente

Greșit: Ciclul de citire testează sfârșitul de fișier înainte de a citi
Corect: Indicatorul de sfârșit de fișier se activează abia după o citire eșuată, deci ultima valoare este prelucrată de două ori; citirea trebuie pusă chiar în condiția ciclului
Greșit: Se încearcă modificarea pe loc a unei valori dintr-un fișier text
Corect: Liniile unui fișier text au lungimi variabile; actualizarea se face prin rescrierea într-un fișier temporar, apoi ștergerea originalului și redenumirea copiei
Greșit: La accesul direct, poziția se calculează în număr de înregistrări, nu în octeți
Corect: Poziționarea se face în octeți: înregistrarea k, numerotată de la 0, începe la octetul k înmulțit cu dimensiunea unei înregistrări
Greșit: Se salvează într-un fișier binar structuri care conțin pointeri
Corect: Se scrie adresa, nu conținutul, iar la o rulare ulterioară adresa nu mai are sens; se folosesc câmpuri de dimensiune fixă, de exemplu tablouri de caractere
Greșit: Se scriu valori numerice în fișier text fără separator între ele
Corect: Fără spațiu sau trecere la linie nouă, 12 și 5 devin la recitire numărul 125; separatorul face parte din formatul fișierului text

Test — 6 întrebări ca la examen

1. Care este principala deosebire dintre un fișier și un tablou unidimensional?
  1. fișierul poate conține doar numere întregi
  2. datele din fișier sunt persistente, iar dimensiunea lui nu se declară în prealabil
  3. tabloul poate fi parcurs, iar fișierul nu
  4. fișierul se încarcă automat în memorie la pornirea programului
Vezi răspunsul
datele din fișier sunt persistente, iar dimensiunea lui nu se declară în prealabil. Fișierul păstrează datele după terminarea programului și nu are dimensiune fixată la compilare, spre deosebire de tablou. A treia variantă e falsă: fișierul se parcurge, doar că secvențial, iar prelucrarea lui e chiar scopul capitolului.
2. Un fișier existent, plin cu date, este deschis pentru scriere în mod obișnuit (fără mod de adăugare). Ce se întâmplă cu conținutul lui?
  1. rămâne neschimbat, iar scrierea începe de la sfârșit
  2. conținutul este golit (trunchiat)
  3. deschiderea eșuează, pentru că fișierul există deja
  4. conținutul este copiat automat într-un fișier de rezervă
Vezi răspunsul
conținutul este golit (trunchiat). Deschiderea pentru scriere trunchiază fișierul existent; datele vechi se pierd. Prima variantă descrie modul append, care trebuie cerut explicit — de aceea este distractorul care înșală cel mai des.
3. De ce un fișier text nu permite, în general, acces direct la componenta cu numărul k?
  1. pentru că fișierele text sunt protejate la scriere
  2. pentru că liniile au lungimi diferite, deci poziția componentei nu se poate calcula
  3. pentru că indicatorul de poziție nu există la fișierele text
  4. pentru că fișierele text nu pot depăși o anumită dimensiune
Vezi răspunsul
pentru că liniile au lungimi diferite, deci poziția componentei nu se poate calcula. Accesul direct presupune o formulă a poziției, care există doar dacă toate componentele au aceeași dimensiune. A treia variantă e falsă: indicatorul de poziție există la orice flux, dar fără dimensiune constantă nu poate fi calculat unde să sară.
4. Într-un fișier binar, fiecare înregistrare ocupă 40 de octeți. La ce octet începe înregistrarea cu numărul de ordine 7, dacă numerotarea începe de la 0?
  1. la octetul 7
  2. la octetul 240
  3. la octetul 280
  4. la octetul 320
Vezi răspunsul
la octetul 280. Poziția este 7 înmulțit cu 40, adică 280, pentru că înaintea înregistrării 7 se află 7 înregistrări complete. Varianta 240 apare când se numără greșit de la 1 și se calculează (7-1) înmulțit cu 40, iar 320 corespunde înregistrării următoare.
5. Cum se determină numărul de înregistrări dintr-un fișier binar cu înregistrări de dimensiune fixă, fără a-l parcurge?
  1. se citește prima înregistrare, care conține numărul total
  2. se poziționează cursorul la sfârșit, se citește poziția și se împarte la dimensiunea unei înregistrări
  3. se numără caracterele de sfârșit de linie
  4. nu se poate determina decât citind toate înregistrările
Vezi răspunsul
se poziționează cursorul la sfârșit, se citește poziția și se împarte la dimensiunea unei înregistrări. Poziția cursorului la sfârșitul fișierului este chiar dimensiunea lui în octeți, iar împărțirea la dimensiunea unei înregistrări dă numărul lor. Numărarea marcajelor de linie este specifică fișierelor text și nu are sens într-un fișier binar.
6. Dintr-un fișier text care conține pe fiecare linie un nume, trebuie ștearsă a treia linie. Care este metoda corectă?
  1. se poziționează cursorul la începutul liniei a treia și se scriu spații peste ea
  2. se copiază toate liniile, mai puțin a treia, într-un fișier temporar, apoi se șterge originalul și se redenumește copia
  3. se deschide fișierul în mod adăugare și se scrie o linie goală la final
  4. se micșorează dimensiunea fișierului cu lungimea liniei a treia
Vezi răspunsul
se copiază toate liniile, mai puțin a treia, într-un fișier temporar, apoi se șterge originalul și se redenumește copia. Ștergerea într-un fișier text se face rescriind conținutul dorit într-un fișier temporar, care apoi înlocuiește originalul. Prima variantă pare eficientă, dar suprascrierea cu spații nu elimină linia — ea rămâne în fișier, doar golită de conținut.
Deschide varianta interactivă — cu AI care îți explică
← Elemente de programare orientată pe obiecte (OOP)Proiectarea și realizarea unui produs software →
BiologieChimieEconomieFilosofieFizicăGeografieInformatică și TICIstorieLogică și argumentareMatematicăPsihologieLimba și literatura română