Sunteți pe pagina 1din 11

Capitolul 10 Fiiere

Obiectiv: Familiarizarea cu memorarea pe suport extern. Activiti: - Prezentarea unor noiuni generale legate de lucru cu fiiere (fiiere text i fiiere binare); - Prezentarea principalelor funcii folosite n lucrul cu fiiere;

10.1 Introducere n lucrul cu fiiere


Un fiier reprezint o secven de date stocat n memoria extern a unui calculator (pe harddisk-uri, dischete, CD-ROM, etc). Memoria extern furnizeaz o capacitate de stocare mult mai mare dect memoria intern, nu este volatil (nu-i pierde coninutul la ntreruperea alimentrii cu energie electric), dar are ca principal dezavantaj viteza de transfer a datelor mult mai redus dect memoria intern. De asemenea, memoriile externe nu dispun de conexiune direct cu procesorul calculatorului. Pentru a putea prelucra informaiile din fiiere, programele trebuie s aduc informaiile din fiiere n memoria intern (RAM) i apoi n variabilele programului pentru efectuarea prelucrrilor necesare asupra informaiilor respective, iar apoi s transfere rezultatele napoi n fiiere. n limbajul C, operaiile cu fiierele se realizeaz prin intermediul unui set de funcii din biblioteca standard de intrare/ieire (I/O), care necesit includerea fiierului header stdio.h. Primul lucru care trebuie fcut atunci cnd vrem s lucrm cu fiiere este s ne definim un pointer ctre o structur de tipul FILE. O structur de tipul FILE este o structur de control a streamurilor. Ea pstreaz informaii cum ar fi adresa de nceput i lungimea zonei tampon a datelor, poziia indicatorului de fiier, poziia indicatorului de sfrit a fiierului, etc. Un stream este un canal logic de comunicaie ntre program i fiierul de pe hard. Toate operiile de citire, i de scriere din / n fiier se realizeaz prin intermediul acestui canal de comunicaie. Deschiderea fiierului, respectiv crearea stream-ului se realizeaz cu ajutorul funciei fopen. Funcia deschide fiierul pe care l specificm prin nume i cale n modul pe care l precizm i creeaz canalul de comunicaie cu fiierul respectiv. n C putem lucra cu 2 tipuri de fiiere: text sau binare. Pentru a se putea accesa informaiile dintr-un fiier, trebuie efectuate urmtoarele operaii: deschiderea fiierului; citirea/scrierea coninutului fiierului; nchiderea fisierului; Deschiderea fiierului este necesar datorit faptului c sistemul de operare trebuie s aloce resurse interne, pentru a se putea accesa coninutul fisierului. Aceste resurse sunt eliberate n momentul nchiderii fiierului respectiv. n momentul deschiderii unui fiier, programatorul trebuie s indice sistemului de operare trei elemente: numele fiierului; modul de accesare al fiierului (citire, scriere, adaugare la sfrit, actualizare - citire i scriere); tipul fiierului: text sau binar; Referitor la tipul fiierului, trebuie facut distincia ntre fiierele binare i fiierele text, atunci cnd programatorul dorete s acceseze (i s modifice) coninutul unui fiier. Diferenele apar la nivelul funciilor de bibliotec pentru citirea i scrierea coninutului fiierelor. Un fiier binar se acceseaz ca o succesiune de octei, crora funciile de citire i scriere din fiier nu le dau nici o interpretare. Un fiier text se acceseaz ca o succesiune de linii de text de lungime variabil, utiliznd un set dedicat de funcii din biblioteca standard. Aceste funcii inspecteaz toate caracterele citite din fiier i ncheie o operaie de citire n momentul n care a fost preluat un caracter '\n' - new line (linie nou).

Programarea Calculatoarelor

Capitolul 10 Fiiere

10.2 Funcii folosite n lucrul cu fiiere


10.2.1 Prezentare general
n limbajul C exist o serie de funcii specializate n lucrul cu fiiere. Pentru a se putea folosi aceste funcii, este necesar includerea fiierului header stdio.h Principalele funcii folosite n lucrul cu fiiere sunt urmtoarele: Nume funcie fopen () fclose () fputch () fgetch () fseek () fprintf () fscanf () feof () ferror () ftell () Descriere funcie Deschide un fiier nchide un fiier Scrie un caracter ntr-un fiier Citete un caracter dintr-un fiier Caut un anumit octet ntr-un fiier Echivalentul lui printf (), folosit pentru un fiier Echivalentul lui scanf (), folosit pentru un fiier Returneaz o valoare dif. de 0 dac se ajunge la sfritul fiierului Returneaz o valoare dif. de 0 dac apare o eroare Returneaz poziia cursorului ntr-un fiier

Tabel 10.1 Principalele funcii folosite n lucrul cu fiiere

Pentru a se putea utiliza un fiier, este necesar folosirea unui pointer, care s fac legtura ntre fiierul respectiv i sistemul I/O din C. Pointer-ul respectiv este un pointer ctre anumite informaii despre fiierul respectiv nume, starea i poziia in care se afl poinetrul de fiier, dimensiune etc. FILE * fisier;

10.2.2 Deschiderea i nchiderea fiierelor


Deschiderea unui fiier se face cu funcia fopen (), care are urmtorul prototip: FILE *fopen (char *nume_fiier, char *mod) Primul parametru (filename) reprezint numele fiierului care urmeaz s se dechid. Al doilea parametru (mod) este un ir de caractere care indic modul de accesare i tipul fiierului. Valorile posibile pentru acest parametru sunt urmtoarele: Valoarea lui mod "rt" "rb" "wt" "wb" "at" "ab" "r+t" "r+b" "w+t" "w+b" "a+t" "a+b" Tipul fiierului Text Binar Text Binar Text Binar Text Binar Text Binar Text Binar Modul de accesare doar citire; dac fiierul nu exist se semnaleaz eroare doar scriere; dac fiierul nu exist, va fi creat, iar dac exist, va fi suprascris doar scriere; dac fiierul nu exist va fi creat, iar dac exist se va adauga la sfritul lui citire i scriere; dac fiierul nu exist se semnaleaz eroare citire i scriere; dac fiierul nu exist va fi creat, iar dac fiierul exist va fi suprascris citire i scriere; dac fiierul nu exist va fi creat, iar dac fiierul exist se va aduga la sfritul su

Tabel 10.2 Moduri de accesare a fiierelor

Programarea Calculatoarelor

Capitolul 10 Fiiere

Dac operaia de deschidere eueaz, funcia returneaz valoarea NULL. Dac deschiderea reuete, funcia returneaz o valoare de tip FILE *, care se folosete n toate operaiile ulterioare asupra fiierului respectiv. Exemplu: crearea (deschiderea) unui fiier i setarea atributului w (pentru a se putea scrie n fiierul respectiv): FILE *fisier; fisier = fopen (exemplu.txt, wt); O versiune mai corect a exemplului anterior este: FILE *fisier; fisier = fopen (exemplu.txt, wt); if (fisier == NULL) { printf (Fisierul nu poate fi creat.); } else { printf (Fisierul a fost creat cu succes); } Aceast variant este recomandat, deoarece utilizatorului i se confirm crearea fiierului dorit, iar n caz contrar (protecie la scriere, disc plin etc.) se va afia un mesaj. Dup ce sunt folosite, fiierele trebuie nchise. Atunci cnd execuia programului se ncheie cu succes (fie prin ncheierea execuiei funciei main (), fie prin apelarea funciei exit() ), toate fiierele deschise n momenul respectiv sunt automat nchise. Dac rularea unui program este ntrerupt forat (prin blocarea execuiei sau prin rularea funciei abort() ), fiierele deschise n momentul respectiv nu sunt nchise. nchiderea unui fiier se face cu funcia fclose (), care are urmtorul prototip: int fclose (FILE *fisier) Parametrul fiier trebuie s fie valoarea returnat de funcia fopen (). Apelarea funciei va avea ca rezultat i scrierea oricrei date rmas n buffer-ul discului pe care se afl fiierul, executnd de asemenea nchiderea fiierului la nivel de sistem de operare. Funcia fclose () returneaz 0 dac operaia de nchidere a fiierului s-a realizat cu succes i EOF dac a intervenit o eroare. Dac un fiier nu este nchis corespunztor pot apare diverse situaii nedorite pierderi de date, fiiere corupte sau/i distruse, posibilitatea apariiei de erori n programul n care se folosete fiierul (sau fiierele) respectiv(e). De asemenea, funcia fclose () distruge asocierea dintre fiierul respectiv i variabila FILE * corespunztoare, astfel nct variabila respectiva poate fi reutilizata.

10.2.3 Determinarea poziiei / setarea cursorului de fiier


Informaiile dintr-un fiier sunt accesate secvenial, iterativ. Orice fiier, odat deschis, are asociat un cursor care indic poziia curent n fiierul respectiv (iniial - nceputul fiierului respectiv). Funciile de scriere i citire din fiiere opereaz ncepand de la poziia curent a cursorului respectivului fiier. Totodat, orice operaie de scriere sau citire avanseaz automat acest cursor cu numrul de octei citii/scrii. Spre exemplu, daca poziia curent este pe octetul 7, scrierea sau citirea a 5 octei avanseaz cursorul pe octetul 12. Poziia curent a cursorului dintr-un fiier se poate afla folosind funcia ftell (): long ftell (FILE *fiier)

Programarea Calculatoarelor

Capitolul 10 Fiiere

Funcia ftell () returneaz poziia (n octei) fa de nceputul fiierului n care se afl cursorul de parcurgere a fiierului. Poziionarea cursorului pe o anumita poziie din fiier se poate face, de asemenea, folosind funcia fseek (): int fseek (FILE *fiier, long pozitie, int referinta) Parametrul fiier trebuie s fie o valoare returnat de funcia fopen (). Parametrul pozitie indic deplasarea n octei fa de referina unde se va poziiona cursorul. Ca referin (al treilea parametru), se pot folosi urmtoarele valori: SEEK_SET fa de nceputul fiierului; SEEK_CUR fa de poziia curent a cursorului respectivului fiier SEEK_END fa de sfritul fiierului Exemplu: program care determin i afieaz dimensiunea n octei a unui fiier: #include <stdio.h> long get_file_size (FILE *fisier) { long pos; long size; /* salvam pozitia curenta a cursorului */ pos = ftell (fisier); /* pozitionare la sfarsitul fisierului */ fseek (fisier, 0, SEEK_END); /* aflam dimensiunea in octeti */ size = ftell (fisier); /* refacem pozitia initiala a cursorului */ fseek (fisier, pos, SEEK_SET); return size; } int main { FILE long char (void) *fisier; size; nume [80];

printf ("Introduceti numele fisierului: "); gets (nume); /* deschidem fisierul pentru citire, binar */ fisier = fopen (nume, "rb"); if (fisier == NULL) { printf ("Nu se poate deschide fisierul %s! \n", nume);

Programarea Calculatoarelor

Capitolul 10 Fiiere

} else { size = get_file_size (fisier); printf ("Fisierul %s are %d octeti. \n", nume, size); fclose (fisier); } return 0; }

10.2.4 Citirea i scrierea din/n fiier


n cazul n care se lucreaz cu fiiere text se folosesc n mod uzual urmtoarele funcii: pentru scriere: sunt folosite funciile fputs () i fprintf (); pentru citire: sunt folosite funciile fgets () i fscanf (); Funciile recomandate pentru lucrul cu fiiere binare sunt urmatoarele: pentru scriere: se folosete funcia fwrite (); pentru citire: se folosete funcia fread (); Observaie: atunci cnd cursorul ajunge la sfritul fiierului, scrierea n fiierul respectiv are ca efect creterea dimensiunii fiierului cu numrul de octei scrii.

Funciile fputs () i fgets () Funciile fputs () i fgets () sunt folosite pentru citirea i scrierea de iruri de caractere n sau dintr-un fiier. Prototipurile acestor funcii sunt urmtoarele: int fputs (char *sir, FILE *fisier); char *fgets (char *sir, int lungime, FILE *fiier); Funcia fputs () scrie n fiierul specificat irul spre care indic pointer-ul sir. Dac apare vreo eroare, funcia fputs () returneaz EOF. Funcia fgets () citete un ir de caractere din fiierul specificat, pn cnd este ntlnit un caracter de linie nou sau atunci cnd au fost citite lungime-1 caractere. Dac este citit un caracter de linie nou, acesta va fi inclus n ir. Funcia va returna irul de caractere ir dac citirea s-a fcut corect i returneaz valoarea NULL dac apare o eroare n timpul citirii. irul rezultat (n urma citirii) se termin cu '\0'. Funciile fscanf () i fprintf () Funciile fscanf () i fprintf () funcioneaz identic cu funciile scanf () i printf (), cu deosebirea c citirea respectiv scrierea se face opereaz asupra unui fiier specificat ca prim parametru, permind folosirea irurilor i a caracterelor de formatare.
int fscanf(FILE *f,char *format,..adresele variabilelelor...); int fprintf (FILE *f,char *format, ...valorile variabilelor...);

Programarea Calculatoarelor

Capitolul 10 Fiiere

Funciile fread () i fwrite () Funciile fread () i fwrite () sunt folosite pentru scrierea datelor n fiierele binare, fr a da nici o interpretare coninutului. Astfel, funciile fread () i fwrite () sunt folosite pentru citirea i scrierea de blocuri de date structurate, fiierul rezultat fiind o copie a coninutului blocului de memorie din care se face scrierea n fiier (n cazul fwrite () ) sau o imagine a coninutului fiierului (n cazul fread ()). Prototipurile funciilor fread () i fwrite () sunt urmtoarele:
size_t fread (void *ptr,size_t noct,size_t nr,FILE *f); size_t fwrite (void *ptr,size_t noct,size_t nr,FILE *f);

n cazul funciei fread (), pointer-ul ptr este un pointer ctre o regiune de memorie care va primi datele din fiierul respectiv, iar n cazul funciei fwrite () pointer-ul ptr este un pointer ctre informaiile care vor fi scrise n fiierul respectiv. Valoarea nr specific numrul de elemente citite sau scrise, fiecare dintre elementele respectiver avnd dimensiunea in octei specificata in parametrul noct. Funcia fwrite () returneaz numrul de elemente scrise n fiier, dac nu apare nici o eroare n timpul scrierii (valoarea returnat va fi egal cu nr dac nu intervine nici o eroare). Funcia fread () returneaz numrul de elemente citite, putnd fi mai mic dect valoarea lui nr, dac se ajunge la sfritul fiierului sau dac apare vreo eroare. Exemplu de folosire a funciei fwrite (): #include <stdio.h> #include <string.h> typedef struct { int varsta; char nume[20]; }student; int main(void) { FILE *f; student st; f = fopen ("fis_binr.bin", "wb"); if (f == NULL) printf ("Fisierul nu se poate crea!"); else { st.varsta = 19; strcpy (st.nume, "Andrei"); /* scrierea structurii in fisier */ fwrite (&st, sizeof(st), 1, f); fclose (f); } return 0; } Exemplu de folosire a funciei fread () (pentru fiierul creat n exemplul anterior):

Programarea Calculatoarelor

Capitolul 10 Fiiere

#include <stdio.h> typedef struct { int varsta; char nume[20]; }student; int main(void) { FILE *f; student st; int n; f = fopen ("fis_binr.bin", "rb"); if (f == NULL) printf ("Fisierul nu se poate deschide!"); else { n = fread (&st, sizeof (st), 1, f); if (n == 1) printf ("%s are %d ani \n", st.nume, st.varsta); else printf ("Nu s-a putut citi inregistrarea din fis."); fclose (f); } return 0; }

10.3 Exemple rezolvate


Exemplul 1: program care citete un fiier text i l afieaz linie cu linie: #include <stdio.h> #include <stdlib.h> int main (void) { FILE *fis; char *sir, *rez; sir = malloc (50 * sizeof (char)); /*iniializarea pointerului */ fis = fopen ("exemplu.txt", "rt"); if (fis == NULL) printf ("Fisierul nu se poate deschide!"); else { while (!feof (fis)) { rez = fgets (sir, 50, fis);

Programarea Calculatoarelor

Capitolul 10 Fiiere

if (rez == NULL) printf ("Nu s-a putut efectua citirea!"); else printf ("%s", sir); } fclose (fis); } free (sir); /*eliberarea memoriei alocate*/ return 0; } Exemplul 2: program care citete de la tastatur un text de mai multe linii i l scrie ntr-un fiier text: #include <stdio.h> #include <stdlib.h> void cit_sir (char *sir) { do { gets (sir); } while (strlen (sir) == 0); } int main (void) { FILE *fis; char sir[50]; int n, i, b; fis = fopen ("2.txt", "wt"); if (fis == NULL) { printf ("Fisierul nu se poate crea ! \n"); } else { printf ("Cate linii doriti sa introduceti? "); scanf ("%d", &n); for (i = 0; i < n; i++) { printf ("Linia %d: ", i + 1); cit_sir (sir); strcat (sir, "\n"); b = fputs (sir, fis); if (b == EOF) printf ("Nu se poate face scrierea ! \n"); } fclose (fis); } return 0; }

Programarea Calculatoarelor

Capitolul 10 Fiiere

Exemplul 3: program care citete de la tastatur cteva nregistrri de tip structur (ex. informaii despre studeni - numele i vrsta) i le scrie ntr-un fiier: #include <stdio.h> #include <string.h> #define DIM 100 typedef struct { int varsta; char nume[20]; }student; student tab[DIM]; int n; void cit_sir (char *sir) { do { gets (sir); }while (strlen (sir) == 0); } int main (void) { FILE *f; int i; printf (Cate inregistrari doriti? ); scanf (%d, &n); for (i = 0; i < n; i++) { printf (Numele persoanei %d: , i + 1); cit_sir (tab[i].nume); printf (Varsta persoanei %d: , i + 1); scanf (%d, &tab[i].varsta); } /*se creeaz un fiier binar*/ f = fopen ("ex_binar.bin", "wb"); if (f == NULL) printf ("Fisierul nu se poate crea!"); else { /*TOATE inregistrarile sunt scrise printr-o apelare*/ fwrite (tab, sizeof (student), n, f); fclose (f); } return 0; } Exemplul 4: program care citete fiierul generat de exemplul anterior si afieaz nregistrrile citite:

Programarea Calculatoarelor

Capitolul 10 Fiiere

#include <stdio.h> #define DIM 100 typedef struct { int varsta; char nume[20]; }student; student tab[DIM]; int n; int main (void) { FILE *f; int i; f = fopen (ex_binar.bin, rb); if (f == NULL) printf (Fisierul nu se poate deschide!); else { n = fread (tab, sizeof (student), DIM, f); for (i = 0; i < n; i++) { printf (Numele %d: %s\n, i+1, tab[i].nume); printf (Varsta %d: %d\n, i+1, tab[i].varsta); } fclose (f); } return 0; }

10.4 Probleme propuse


S se realizeze un program care copiaz dintr-un fiier text ntr-un alt fiier text doar liniile care conin un anumit cuvnt, introdus de la tastatur. 2. Se d un fiier text. S se determine numrul de linii din fiier. S se creeze un alt fiier, cu liniile din primul aparnd n ordine invers. 3. S se realizeze un program care terge un anumit student (al crui nume este introdus de la tastatur) din baza de date creat cu penultimul exemplu rezolvat (Exemplul 3). Indicaie: Intrucat nu exist nici o modalitate de a micora dimensiunea unui fiier, pentru a terge o nregistrare din fiier se poate proceda n dou moduri: a) se ncarc informaiile din fiier n tabloul de structuri, se inchide fiierul, se elimin din tablou elementul ters, se suprascrie fiierul prin deschiderea lui cu atributul w, operaie urmat de scrierea tabloului de structuri n fiier i nchiderea fiierului; b) se genereaza un alt fiier care s conin toate nregistrarile din cel iniial, mai putin cea care trebuie tears. Apoi se poate utiliza funcia remove pentru a sterge fisierul initial si rename pentru a redenumi fisierul generat la numele iniial: int remove (char *filename); int rename (char *old_name, char *new_name) La funcia remove, parametrul filename reprezint numele fiierului care se va terge. La funcia rename, parametrul old_name i new_name reprezint numele iniial respectiv cel final al fiierului). 1.

Programarea Calculatoarelor

Capitolul 10 Fiiere

n momentul aplicrii funciilor, fiierele respective trebuie s fie nchise, alfel funciile eueaz! Funciile returneaz valoarea 0 dac operaia a reuit sau o valoare diferit de 0 n caz de eec. 4. Un client lanseaz o precomand la o firm speificnd: nume client (30 de caractere) produs comandat (30 de caractere) cantitatea comandat (ntreg) Pentru a onora precomanda firma caut produsul comandat n depozit, i trimite clientului care a lansat comanda un raspuns de forma: adresa client mesaj de forma: Produsul exist i cost .sau Produsul nu exist pe stoc. Pentru a trimite aceste raspunsuri firma folosete o agend coninand perechi: o nume client o adres client Scriei un program care folosete fisierele binare comenzi, depozit i agenda i creeaz fiierul text rspunsuri.

10.5 Intrebari recapitulative


1. 2. 3. 4. 5. Care sunt tipurile de fisiere cu care se poate lucra in C? Care este diferenta dintre ele? Care sunt functiile care permit deschiderea respectiv inchiderea unui fisier? Cum se utilizeaza? Care sunt modurile in care poate fi deschis un fisier? Precizati modul de utilizare al functiilor fwrite / fread. Precizati modul de utilizare al functiilor fputs, fgets.

S-ar putea să vă placă și