Sunteți pe pagina 1din 17

CURS

13

Prelucrare
a
fiierelor

Sumar
Ierarhia de clase pentru lucrul
cu fiiere Deschiderea fiierelor
nchiderea fiierelor
Intrri si ieiri la nivel de fiier
Accesul le datele dintr-un fiier
Aplicaii

n practic, programele lucreaz cu un volum mare de date. Stocarea datelor se


face pe diverse suporturi magnetice (hard - disc, dischet) sub form de fiiere.
Se numete fiier o colecie de date omogene (adic de acelai tip), stocate pe
suport extern i accesat printr-un nume care reprezint numele fiierului.
n C, un fiier poate fi orice, de la un fiier pe disc i pn la un terminal sau o
imprimant. Un flux se poate socia unui anumit fiier executnd o operaie de deschidere.
Odat ce fiierul a fost deschis, poate avea loc transferul de informaii ntre acest fiier i
programul realizat.
Se lucreaz cu dou tipuri de fiiere, i anume: text i binare. Fiierele text sunt
fiierele n care datele sunt memorate sub forma unei succesiuni de caractere. Fiecare
caracter este memorat prin utilizarea codului ASCII pentru acel caracter.
Fiierele binare sunt fiiere organizate ca date binare (octeii nu sunt considerai
ca fiind coduri de caractere). Acestea pot fi prelucrate folosind funciile fread i
fwrite. n acest caz se consider c nregistrarea este o colecie de articole. Articolul

este o dat de un tip oarecare (predefinit sau definit de utilizator). La o citire, se transfer
ntr-o zon special, numit zon

tampon (buffer), un numr de articole care se

presupune c au o lungime fix. n mod analog, la scriere se transfer din yona tampon un numr
de articole de lungime fix.

Ierarhia de clase pentru lucrul cu fiiere


Pentru a putea efectua operaii cu fiiere programele create trebuie s includ fiierul
de antet fstream.h.
streambuf

filebuf

ios

fstreambase

istream

ostream

iostream

ifstream

fstream

ofstream

La prelucrarea fiierelor se folosesc obiecte ale clasei filebuf care este o clas derivat a
clasei streambuf. Obiectele clasei filebuf sunt utilizate de clase specifice pentru operaii
cu fiiere i care aparin ierarhiei care are ca rdcin clasa ios.
Clasa fstreambase este o clas de baz pentru urmtoarele 3 clase:
ifstream

- folosit la operaii de intrare (citire);

ofstream

- folosit la operaii de ieire (scriere);

fstream

- folosit la operaii de intrare/ieire (citire/scriere).

Aceste 3 clase, au fiecare, nc o clas de baz i anume:


ifstream

- deriv din clasa istream;

ofstream

- deriv din clasa ostream;

fstream

- deriv din clasa iostream.

De aici rezult c pentru obiectele acestor clase se pot aplica funciile membru ale
claselor lor de baz, inclusiv suprancrcarea operatorilor se inserare i tergere.

Deschiderea unui fiier


Prelucrarea unui fiier de pe disc ncepe cu deschiderea lui. n acest fel se poate
proceda n unul din urmtoarele moduri:
-

se utilizeaz funcia membru open cu un obiect al uneia din clasele ifstream,


ofstream sau fstream instaniat fr parametri.

Se utilizeaz parametri pentru deschiderea fiierului la instanierea obiectelor.

n primul caz, obiectele se instaniaz folosind constructori implicii.


Fie, de exemplu, instanierea:
ifstream obiect;
Obiectului obiect i se ataeaz un fiier concret la apelul funciei open de forma:
obiect.open()
Funcia open este definit n clasa fstreambase i este suprancrcat n clasele
derivate din aceasta. Ea are prototipul:

void open(char *fisier, int mod, int protectie)


Parametrul fiier este un pointer spre un ir de caractere care definete numele i
extensia fiierului care se deschide, precum i calea spre fiierul respectiv, dac acesta nu se afl
n directorul curent.
Parametrul mod definete modul de deschidere al fiierului. n acest scop se pot
folosii enumeratorii definii n clasa ios astefel:
in:

- fiierul se deschide n intrare (citire);

out:

- fiierul se deschide n ieire (scriere);

ate:

- dup deschiderea fiierului, poziia curent n fiier este sfritul


3

fiierului; acest mod se folosete pentru a face cutri n fiier ncepnd


cu
sfritul acestuia;
app:

- deschidere pentru a aduga nregistrri la sfritul fiierului;

trunc:

- dac fiierul exist, coninutul lui se pierde i se creeaz un fiier nou;


el este incompatibil cu opiunile ate i app;

nocreate:

- fiierul care se deschide cu aceast opiune trebuie s existe; el nu se


deschide n creare;

noreplace: - dac fiierul exist i este prezent opiunea out, atunci deschiderea este
admis numai dac se utilizeaz opiunea ate sau app;
binary: - fiierul se deschide pentru a fi prelucrat binar; n mod implicit se
consider c fiierele sunt prelucrate pe caractere (n mod text).
La o deschidere de fiier se pot folosi mpreuna mai multe opiuni, folosind
operatorul | (sau logic pe bii).
Pentru obiectele clasei ifstream, opiunea in este implicit, iar pentru cele ale
clasei ofstream, opiunea out este implicit.
Parametrul protecie definete modul de acces la fiier. n mod implicit acest
parametru are valoarea zero, i aceasta nseamn c fiierul respectiv nu are restricii la
acces.
Rezultatul operaiei de deschidere de fiier poate fi testat cu ajutorul cuvntului de stare
al streamului pentru care s-a apelat funcia open.

Exemple:
1.ifstream fisier;
//se deschide fiierul fis.dat in citire
fisier.open(fis.dat,ios::nocreate);
4

//se testeaza starea obiectului fisier dupa deschidere


if(fisier)
{ //deschidere corecta

}
else
{
cout<<eroare de dechidere \n;

}
Opiunea ios::in este implicit.
2. ofstream fis_iesire;
//se deschide fisierul factura.dat
fis_iesire.open(factura.dat);
if(!fis_iesire)
{ cout<<eroare de deschidere ;

}
3. ofstream fis;
//se deschide pentru adaugare fisierul binar stoc.dat
fis.open(stoc.dat, ios::app | ios::binary);
//se testeaza starea obiectului fis dupa deschidere
if(!fis)
{
cout<<eroare la deschidere \n;

}
else
{
//deschidere corecta

}
Cea de a doua posibilitate de a deschide un fiier este aceea de a folosi parametrii
corespunztori la instanierea obiectelor claselor ifstream, ofstream sau fstream. n acest
caz, constructorul apelat pentru instanierea obiectului apeleaz n mod automat funcia
open. Constructorii care deschid fiierele la instanierea obiectelor claselor amintite mai sus,
au aceiai parametri ca i funcia open.
nume_clasa(char *fisier, int mod, int protectie)
unde:
nume_clasa

- este ifstream, ofstream, sau fstream.

Parametrul protectie este i n acest caz un parametru implicit, avnd valoarea


implicit egal cu zero.
Exemplele de mai sus pot fi rescrise astfel:
ifstream

1.

fisier(fis.dat,ios::nocreate);
if(fisier)
{ //deschidere corecta

}
else
{
cout<<eroare de dechidere \n;

}
2. ofstream fis_iesire(factura.dat);
if(!fis_iesire)
{ cout<<eroare de deschidere ;

}
3. ofstream fis(stoc.dat, ios::app |
ios::binary);
//se testeaza starea obiectului fis dupa deschidere
if(!fis)
{
cout<<eroare la deschidere \n;

}
else
{
//deschidere corecta

}
Dup deschiderea unui fiier, se pot face prelucrri asupra fiierului respectiv.

nchiderea unui fiier


Dup terminarea prelucrrii unui fiier, n conformitate cu modul n care a fost
deschis, acesta trebuie nchis. nchiderea unui fiier se realizeaz cu ajutorul funciei
close. Aceasta se apeleaz n mod obinuit:
obiect.close();
sau
pobiec->close();

unde
obiect

- este o instaniere a uneia din clasele ifsteam, ofstream sau fstream.

n mod analog pobiect este un pointer spre unul din tipurile implementate prin
aceste clase.

Intrri, ieiri n lucrul cu fiiere


La prelucrarea fiierelor pstrate pe disc se pot folosi funciile membru ale
claselor istream, ostream sau iostream, acestea fiind clase de baz pentru
clasele
specifice prelucrrii fiierelor de pe disc. n particular, se pot folosi operatorii de inserare
i extragere pentru operaii de scriere cu format i respectiv citire cu format dintr-un
fiier de pe disc.
Intrarea unui singur caracter se poate realiza cu ajutorul funciei membru get a clasei
istream. Ea are prototipul:
istream& get(char &);
Se obinuiete s se spun c funcia get extrage un caracter din streamul curent i-l
pstreaz n zona de memorie referit de parametrul formal.
Funcia get nu realizeaz avansul peste caracterele albe, deci ea extrage din
streamul curent caracterul, indiferent dac acesta este un spaiu alb sau nu.
Funcia get are i alte prototipuri care permit extragerea unui ir de caractere din
streamul curent i anume:
istream& get(unsigned char *zona, int max, int
term=\n);
istream& get(signed char *zona, int max, int
term=\n);
Aceast funcie extrage din streamul curent cel mult max-1 caractere sau pn la
ntlnirea caracterului dat de valoarea lui term. Caracterele respective se pstreaz n zona
de memorie spre care pointeaz zona.
8

Dup caracterele extrase din streamul curent se pstreaz caracterul NUL (\0).
Terminatorul definit de term nu se pstreaz n zona de memorie spre care pointeaz
zona.
Extragerea caracterului definit de term din streamul de intrare este posibil cu
ajutorul funciei getline. Aceasta are prototipul similar cu funcia get:
istream& getline(char *zona, int max, int term =\n);
Parametrii formali ai funciei getline au acelai sens ca i n cazul funciei get.
Extragerea binar a datelor din streamul curent se realizeaz folosind funcia read.
Aceasta are prototipul:
istream& read(unsigned char *zona,
int

n);

istream& read(signed char *zona, int


n);
Funcia extrage n octei din streamul curent i i transfer n zona de memorie spre care
pointeaz zona.
Ieirea unui singur caracter se poate realiza cu ajutorul funciei put a clasei
ostream. Aceasta are prototipul:
ostream& put(char c);
Pentru a afia n octei, se poate utiliza funcia membru write a clasei ostream. Ea
are urmtoarele prototipuri:
ostream& write(const signed char *sir, int n);
ostream& write(const unsigned char *sir, int n);

Funcia write afieaz n caractere chiar dac printre cei n octei spre care
pointeaz sir se ntlnete caracterul NUL. Esena acestor funcii este faptul c, asupra lor bii de
format nu au nici un efect.

Accesul aleator la datele din fiier


Accesul aleator se poate realiza folosind funcii membru specifice ale claselor ofstream i
ifstream.
Ptr. ofstream:
long tellp() - returneaz poziie curent
seekp() - poziionare pe o anumit poziie n fiier
Ex.: fisier.seekp(n, beg(sau cur sau end)) unde n este deplasamentul n octei fa
de nceput, curent, respectiv sfrit.
Ptr. ifstream:
long tellg() - returneaz poziie curent
seekg() - poziionare pe o anumit poziie n fiier
Ex.: fisier.seekg(n, beg(sau cur sau end)) unde n este deplasamentul n octei fa
de nceput, curent, respectiv sfrit.

Aplicaii
1. Se citeste un fisier TEXT ce contine numere intregi despartite prin spatiu sau ENTER. Sa
se afiseze minimul si maximul din acel fisier.
#include<iostream.h>
#include<fstream.h>
#include<values.h>
void main()
{
ifstream f("d:\\LaboratorOOP\\numar.txt");
/*
ifstream f;
f.open("numar.txt");
*/
if(!f)

//sau f=NULL

10

{
cout<<"Eroare
return;

la

deschiderea

fisierului!"<<endl;

}
int x,max=-MAXINT,min=MAXINT;
f.seekg(0,ios::beg);
//ne pozitionam la inceputul fisierului
while(!f.eof())
{
f>>x;
if (max<x)
max=x;
else if (min>x)
min=x;
}
f.close();
cout<<"Maximul este: "<<max<<endl;
cout<<"Minimul este: "<<min<<endl;
}

2. Se citeste un fisier iext ce contine numere intregi despartite prin spatiu sau ENTER. Se cere a
se calcula si afisa pe ecran suma tuturor valorilor numerice din fisier si numarul de elemente
strict negative.
#include<iostream.h>
#include<fstream.h>
void main()
{
ifstream f("numar.txt");
if(!f) //sau f=NULL
{
cout<<"Eroare la
return;
}

//sau: fstream f("numar.txt",ios::in);

deschiderea

fisierului!"<<endl;

int x[100], n_neg=0, s=0, i;


f.seekg(0,ios::beg);

//ne pozitionam la inceputul fisierului

i=0;
while(!f.eof())
{
f>>x[i];
if(x[i]<0)
n_neg++;
s+=x[i++];
}
f.close();

11

cout<<"Numarul elementelor negative: "<<n_neg<<endl;


cout<<"Suma tuturor elementelor: "<<s<<endl;
}

3. Se citeste un fisier TEXT ce contine numere intregi despartite prin spatiu sau ENTER.
Sa se afiseze minimul si maximul din acel fisier. Se va defini o clasa ptr numerele intregi
din fisier.
#include<iostream.h>
#include<fstream.h>
#include<values.h>
class numar
{
int n;
public:
int& retur();
friend istream& operator>>(istream&,numar&);
};
int& numar::retur()
{
return n;
}
istream& operator>>(istream& a,numar& b)
{
a>>b.n;
return a;
}
void main()
{
ifstream f("d:\\ LaboratorOOP\\numar.txt ");
if(!f)
{
cout<<"Eroare la deschiderea fisierului!"<<endl;
return;
}
numar x;
int max=-MAXINT;
int min=MAXINT;
f.seekg(0,ios::beg);
while(!f.eof())
{
f>>x;
if (max<x.retur())
max=x.retur();
else if (min>x.retur())
min=x.retur();
}
cout<<"Minimul este: "<<min<<endl;

12

cout<<"Maximul este: "<<max<<endl;


}

4. Se citeste un sir de la tastatura pana la intalnirea caracterului "$". Dupa citire datele se
scriu intr-un fisier text si se preiau din fisierul respectiv si se face contorizarea fiecarei vocale
din fisier.
#include<iostream.h>
#include<fstream.h>
#include<stdio.h>
void main()
{
char c;
int a=0,e=0,i=0,o=0,u=0;
ofstream f("d:\\ LaboratorOOP\\numar.txt ");
if(!f)
{
cout<<"Eroare la deschidere."<<endl;
}
do{
c=getchar();
switch(c)
{
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
}
if(c!='$')
f.put(c);

a++;
e++;
i++;
o++;
u++;

break;
break;
break;
break;

//ar fi mers si f<<c;

}while(c!='$');
f.close();
ofstream g("d:\\ LaboratorOOP\\numar.txt ");
if(!g)
{
cout<<"Eroare la deschidere fisierului de citire."<<endl;
}
g<<"Vocala a se gaseste de : "<<a<<" ori.\n";
g<<"Vocala e se gaseste de : "<<e<<" ori.\n";
g<<"Vocala i se gaseste de : "<<i<<" ori.\n";
g<<"Vocala o se gaseste de : "<<o<<" ori.\n";
g<<"Vocala u se gaseste de : "<<u<<" ori.\n";
g.close();
cout<<"Opratia de contorizare a vocalelor a reusit!"<<endl;
}

13

5. Sa se sumeze valorile numerice dintr-un fisier text.


#include<iostream.h>
#include<string.h>
#include<stdlib.h>
#include<fstream.h>
#include<stdio.h>
void main()
{
char a[255], separator[]="
double s=0;

,",cifre[]="0123456789.+-",*p;

fstream f("valori.txt",ios::in);
if(!f)
{
cout<<"Eoare la deschiderea fisierului."<<endl;
return;
}
while(!f.eof())
{
f.getline(a,255,'\n');
p=strtok(a,separator); //se separa sirul folosind ca separator
spatiul sau virgula
while (p)
{
if (strspn(p,cifre)==strlen(p))
s+=atof(p);
cout<<p<<"\n";
p=strtok(NULL,separator);
}
}
cout<<"Suma este: "<<s<<endl;
}

6. Sa se realizeze un program care tine in evidenta o agenda telefonica. Se vor


supraincarca operatorii << si >>, precum se cere lucrul cu fisiere cu transfer in si din
fisier.
#include<iostream.h>
#include<fstream.h>
#include<string.h>
class agendatelefon {
char nume[80];
int codzona;
int prefix;
char numar[11];
public:

14

friend ostream &operator<< (ostream & stream, agendatelefon o);


friend istream &operator>> (istream & stream, agendatelefon &o);
};
//Afiseaza numele si numarul de telefon
ostream &operator<< (ostream &stream, agendatelefon o)
{
stream<<o.nume<<" ";
stream<<"("<<o.codzona<<")";
stream<<o.prefix<<"-";
stream<<o.numar<<"\n";
return stream;
}
//Introduce nume si numere de telefon
istream &operator>>(istream &stream,agendatelefon &o)
{
cout<<"Introduceti numele: ";
stream>>o.nume;
cout<<"Introduceti coudul zonei: ";
stream>>o.codzona;
cout<<"Introduceti prefixul: ";
stream>>o.prefix;
cout<<"Introduceti numarul: ";
stream>>o.numar;
cout<<'\n';
return stream;
}
void main()
{
agendatelefon a;
char c;
fstream f("telefon.txt",ios::in| ios::out| ios::app);
if(!f)
{
cout<<"Nu pot deschide fisierul agenda de telefon\n";
return;
}
do
{

cout<<endl;
cout<<"1. Introduceti abonat de la tastatura cu afisare pe ecran si
in fisier\n";
cout<<"2. Afiseaza lista abonati pe ecran cu preluare din
fisier\n";
cout<<"3. Parasiti programul\n";
cout<<"Alegeti optiunea: ";
cin>>c;
switch(c)
{
case '1':

15

cin>>a;
cout<<"Intrarea este: ";
cout<<a; //afiseaza pe ecran
f<<a; /* scrie in fisier (este una dintre cele mai
interesante facilitati ale limbajului, adica, odata supraincarcat
oeratorul << ni se permite scrierea directa in fisier) */
break;
case '2':
char ch;
f.seekg(0,ios::beg);
while(!f.eof())
{
f.get(ch);
cout<<ch;
}
cout<<endl;
break;
case '3':
f.close();
}
} while(c!=3);
}

7. Operatii pe fisiere binare. Calculul minimului si maximului dintr-un fisier ce contine


numere intregi.
#include<iostream.h>
#include<fstream.h>
void main(void)
{
int v[4]={1, -5, 200, 98};
int i;
ofstream
out("numere.dat",ios::out|ios::binary);
if(!out)
{
cout<<"Nu pot deschide fisierul.\n";
return;
}
out.write((unsigned
out.close();

char*)

&v,

sizeof

v);

for(i=0;i<4;i++)
v[i]=0; //curatim matricea
ifstream
in("numere.dat",ios::in|ios::binary);
if(!in)
{
cout<<"Nu pot deschide fisierul.\n";

16

return;
}
in.read((unsigned char*) &v, sizeof v);
//aflati cati octeti au fost cititi
cout<<in.gcount()<<" octeti cititi.\n";
int max, min;
max=v[0];
min=v[0];
for(i=1;i<4;i++)
if(v[i]<min)
min=v[i];
else
if(v[i]>max) max=v[i];
for(i=0;i<4;i++)
cout<<v[i]<<" ";
cout<<endl<<"Maximul este:"<<max<<'\t'<<"minimul este: "<<min<<endl;
in.close();
}

Teme propuse spre rezolvare:


1. Se citete un fiier text format din valori intregi despartite prin spatiu sau enter. Sa
se calculeze numarul de numere pozitive i suma lor, respectiv, numarul de
numere negative si suma lor.
2. Problema cu agenda telefonica din acest laborator sa se modifice pentru lucrul cu
fisiere binare.
3. Asemanatoare problemei cu agenda telefonica sa se enune si rezolve o problema
folosind fiiere binare.

Lect. Univ. Mircea Musan

17