Fisiere in C si C++
description
Transcript of Fisiere in C si C++
Fiiere in C si C++
Fiiere in C si C++1. Operaii de intrare / ieire.
In limbajul C nu exist instruciuni de intrare / ieire. Operaiile de intrare / ieire sunt realizate prin apelul unor funcii ale sistemului de operare. Acestea sunt implementate prin funcii, sub o form compatibil pentru diversele sisteme de operare (sunt portabile).
Un fiier este o colecie ordonat de articole (nregistrri) pstrate pe un suport extern de memorie i identificate printr-un nume.
Pentru fiierul standard de intrare , datele sunt introduse de la tastatur.
Pentru fiierul standard de ieire , rezultatele sunt afiate pe terminalul standard de ieire.
Mesajele de eroare se afieaz n fiierul standard de eroare .
Fiierul are un articol care marcheaz sfritul fiierului. Pentru fiierul standard de intrare de la tastatur, sfritul de fiier, pentru sistemele de operare DOS i Windows se genereaz prin Ctrl-Z (pentru Unix prin Ctrl-D).
Operaiile specifice prelucrrii fiierelor sunt.
deschiderea unui fiier
nchiderea unui fiier
creerea unui fiier
citirea de articole din fiier (consultarea fiierului)
actualizarea (sau modificarea) fiierului
adugare de articole la sfritul fiierului
poziionarea n fiier.
tergerea unui fiier
schimbarea numelui unui fiier
Prelucrarea fiierelor se face pe dou niveluri:
nivelul inferior, care apeleaz direct la sistemul de operare.
nivelul superior, care utilizeaz structuri speciale FILEFunciile de pe nivelul superior nu asigur o independen total fa de sistemul de operare.
Funciile standard de intrare / ieire au prototipurile n fiierul antet .2. Fiiere text i fiiere binare
ntr-un fiier text, toate datele sunt memorate ca iruri de caractere, organizate pe linii, separate ntre ele prin marcajul sfrit de linie \n .
ntr-un fiier text spaiul de memorare pe disc nu este folosit n mod eficient pentru datele numerice (astfel ntregul 12345 ocup 5 octei).
ntr-un fiier binar, datele sunt pstrate n formatul lor intern (2 octei pentru int, 4 octei pentru float, etc).
La fiierele text marcajul de sfrit de fiier (caracterul 0X1A) exist fizic n fiier. La ntlnirea acestui caracter funcia fgetc() ntoarce EOF (-1). Marcajul de sfrit de fiier se genereaz de la tastatur prin Ctrl-Z.
n cazul fiierelor binare, marcajul de sfrit de fiier nu exist fizic n fiier, ci este generat de funcia fgetc().n MSDOS (i n Unix), la nivelul liniei de comand intrrile i ieirile standard pot fi redirectate n fiiere disc, fr a opera nici o modificare la nivelul programului. Astfel:
< redirecteaz intrarea standard ctre fiierul specificat
> redirecteaz ieirea standard ctre fiierul specificat
Fiierul standard de eroare nu poate fi redirectat.
Fiierul specificat poate fi:
con pentru consola sistem (tastatura, respectiv ecranul)
prn pentru imprimanta paralelcom1 pentru interfaa serial de datenume_fiier pentru un fiier discNUL pentru perifericul nul.
Exemple:
> test.exe > prn redirecteaz ieirea programului la imprimant> test.exe < f1.dat > f2.dat redirecteaz att intrarea ct i ieirea programului
3. Accesul la fiiere.
Fiierele disc i fiierele standard sunt gestionate prin pointeri la structuri specializate FILE, care se asociaz fiecrui fiier pe durata prelucrrii.
Fiierele standard au pointerii predefinii: stdin, stdout, stderr, stdprn, stdaux.
Declararea unui pointer la fiier se face prin:
FILE *pf;
1. deschiderea unui fiier:nainte de a fi prelucrat, un fiier trebuie s fie deschis. Prin deschidere:
se asociaz unui nume de fiier un pointer la fiier se stabilete un mod de acces la fiier
Pentru deschiderea unui fiier se folosete funcia cu prototipul:
FILE *fopen(char *nume_fisier, char *mod_acces);
Prin deschiderea unui fiier se stabilete o conexiune logic ntre fiier i variabila pointer i se aloc o zon de memorie (buffer) pentru realizarea mai eficient a operaiilor de intrare / ieire. Funcia ntoarce:
un pointer la fiier, n caz c deschiderea fiierului se face n mod corect
NULL dac fiierul nu poate fi deschis.
Vom considera mai nti dou moduri de acces :
citire (sau consultare) r citirea dintr-un fiier inexistent va genera eroare
scriere (sau creare) w - dac fiierul exist deja, el va fi ters
Fiierele standard nu trebuiesc deschise.
Redirectarea unui fiier deschis poate fi realizat cu:
FILE* freopen(char* nume, char* mod, FILE* flux));
Fiierul deschis este nchis i este deschis un nou fiier avnd ca surs fluxul, numele i modul de acces specificai ca parametri. O utilizare important o constituie redirectarea fluxului standard de intrare: datele vor fi citite din fiierul specificat, fr a face nici o modificare n program.
2. nchiderea unui fiier
Dup terminarea prelucrrilor asupra unui fiier, acesta trebuie nchis. Un fiier este nchis automat la apelarea funciei exit().int fclose(FILE *pf);
funcia ntoarce 0 la nchidere normal i EOF la producerea unui incident
fiierele standard nu se nchid de ctre programator
n cazul unui fiier de ieire, se scriu datele rmase nescrise din buffer n fiier, aa c operaia de nchidere este obligatorie
n cazul unui fiier de intrare, datele necitite din bufferul de intrare sunt abandonate
se elibereaz bufferele alocate
se ntrerupe conexiunea pointer fiier
Secvena urmtoare deschide un fiier cu un nume dat i apoi l nchide.
FILE *pf = fopen(test1.dat, w);
fclose(pf);
4. Operaii de intrare ieire.
Tip fiierConversieUnitate transferatFuncii folosite
TextfrCaracterfgetc(), fputc()
Liniefgets(), fputs()
cuLiniifscanf(). fprintf()
binarfrArticol (structur)fread(), fwrite()
4.1. operaii de intrare / ieire la nivel de caracter
Scrierea unui caracter ntr-un fiier se face folosind funcia:
int fputc(int c, FILE *pf);
Funcia ntoarce primul parametru sau EOF, n caz de eroare.
Citirea unui caracter dintr-un fiier se face cu funcia:
int fgetc(FILE *pf);
Funcia ntoarce ca rezultat urmtorul caracter citit din fiier, convertit n ntreg fr semn sau EOF dac s-a citit sfrit de fiier sau s-a produs o eroare la citire.
Scriei un program care realizeaz copierea unui fiier. Numele celor doua fiiere (surs i destinaie) sunt citite de la terminal.
#include
/* copierea unui fisier */
void copiere1(FILE *, FILE *);
void main(void){
char numes[12], numed[12];
gets(numes);
gets(numed);
FILE* s = fopen(numes,r);
FILE* d = fopen(numed,w);
copiere1(d, s);
fclose(s);
fclose(d);
}
void copiere1(FILE *d, FILE *s) {
int c;
while ((c=fgetc(s)) != EOF)
fputc(c, d);
4.2. }4.3. operaii de intrare / ieire pentru iruri de caractere
char *fgets(char *s, int n, FILE *pf);
citete caractere din fiierul cu pointerul pf, pn la ntlnirea primului caracter \n (cel mult n-1 caractere) n tabloul s; pune la sfrit \n i \0 ntoarce s sau NULL la ntlnire sfrit de fiier sau la eroare
Scriei o funcie care simuleaz funcia fgets().
char *fgets(char *s, int n, FILE *pf) {
char c;
char *psir = s;
while (--n > 0 &&(c=fgetc(pf))!=EOF)
if((*psir++=c)==\n)
break;
*psir=\0;
return (c==EOF && psir==s) ? NULL: s;
}
int fputs(char *s, FILE *pf);
copiaz irul n fiierul de ieire
nu copiaz terminatorul de ir \0 ntoarce un rezultat nenegativ (numrul de caractere scrise n fiier), sau EOF la producerea unei erori
Scriei o funcie care simuleaz funcia fputs().
int fputs(char *s, FILE *pf)
{ int c, n=0;
while (c = *s++){
fputc(c, pf);
n++;
}
return (ferror(pf)) ? EOF: n;
}
Copierea unui fiier folosind funcii orientate pe iruri de caractere are forma:
#define MAX 100
void copiere2(FILE *d, FILE *s){
char linie[MAX];
while(fgets(linie, MAX, s))
fputs(linie, d);
}
Revenim acum asupra modurilor de acces la disc. Sunt posibile urmtoarele situaii:
1. fiierul nu exist; dorim s-l creem i s punem informaii n el
w - deschidere pentru scriere, noile scrieri se fac peste cele vechi2. fiierul exist deja; dorim s extragem informaii din el
r - deschidere pentru citire, fiierul trebuie s existe deja r+ - citire i scriere ; fiierul trebuie s existe
3. fiierul exist deja; dorim s adugm informaii la el, pstrnd informaiile deja existente
a - deschidere pentru adugare, toate scrierile se adaug la sfritul fiierului existent sau nou creat a+ - citire i adugare; dac fiierul nu exist, el va fi creat4. fiierul exist deja; dorim s punem alte informaii n el tergnd pe cele existente
w+ - citire i scriere; dac fiierul exist deja el este tersModul de acces binar se specific cu sufixul b. Astfel avem: rb, w+bModul text este considerat implicit, dar poate fi specificat explicit prin t.4.3. operaii de intrare / ieire cu format
scrierea cu format
int fprintf(FILE *pf, char *format, lista_expresii);
transfer n fiierul specificat, valorile expresiilor, convertite, potrivit formatului n caractere
ntoarce numrul de caractere scrise, sau o valoare negativ, dac s-a produs o eroare.
Un descriptor de conversie din format ncepe prin % i poate avea un mai muli specificatori opionali, care preced descriptorul:
%[indicator][lime][.precizie][spec_lung]descriptor;
Indicatorul poate avea una din valorile:
- aliniere stnga
+ afiare numere cu semn
0 completare stnga cu zerouri
adaugare spaiu naintea primei cifre, dac numrul este pozitiv# %#o - scrie 0 iniial %#x - scrie 0x %#e,f,g,E,G scrie punctul zecimal i nu elimin zerourile la sfrit
Limea numr ce indic limea minim a cmpului n care se face scrierea.
* limea este dat de argumentul urmtor
Precizia este un numr interpretat diferit n funcie de descriptorul folosit.Astfel:%e, %E, %f numrul de cifre dup punctul zecimal%s numrul maxim de caractere afiate%g, %G numrul de cifre semnificative%d, %i numrul minim de cifre (cu zerouri n fa)
Specificarea lungimii se face prin:
H shortl longL long double citirea cu format
int fscanf(FILE *pf, char *format, lista_adrese_variabile);
se citesc date din fiierul pf, sub controlul formatului, iniializndu-se variabilele din list
funcia ntoarce numrul de cmpuri citite sau EOF n caz de producere a unui incident la citire sau ntlnire a marcajului de sfrit de fiier.
4.4. intrri / ieiri n modul de acces binar
sunt operaii de transfer (citiri / scrieri) fr conversii
se fac la nivel de articol
poziia n fiier este actualizat dup fiecare citire / scriere
unsigned fread(void *zona, unsigned la, unsigned na, FILE *pf);
citete cel mult na articole, de lungime la fiecare, din fiierul pf n zona
ntoarce numrul de nregistrri citite sau 0 n caz de eroare sau sfrit de fiier
unsigned fwrite(void *zona, unsigned la, unsigned na, FILE *pf);
scrie na articole de lungime la, din zona n fiierul pf ntoarce numrul de articole scrise.
Pentru a copia un fiier binar (sau text) folosind funciile fread() i fwrite() vom considera lungimea articolului 1 octet.
void copiere3(FILE * d, FILE * s) {
int noc; /* numarul de octeti cititi */
char zona[MAX];
while((noc=fread(zona, 1, MAX, s)) > 0)
fwrite(zona, 1, noc, d);
}
5. Operaii pentru fiiere cu acces direct.
5.1. Poziionarea n fiier
int fseek(FILE *pf, long depl, int orig);
modific poziia curent n fiierul cu pointerul pf cu depl octei relativ la cel de-al treilea parametru orig, dup cum urmeaz:
fa de nceputul fiierului, dac orig=0 (sau SEEK_SET) fa de poziia curent, dac orig=1 (sau SEEK_CUR)
fa de sfritul fiierului, dac orig=2 (sau SEEK_END)
ntoarce rezultatul 0 pentru o poziionare corect, i diferit de 0 n caz de eroare.
void rewind(FILE *pf);
realizeaz o poziionare la nceputul fiierului, fiind echivalent cu:
fseek(pf, 0L, SEEK_SET);
long ftell(FILE *pf);
ntoarce poziia curent n fiier, exprimat prin numrul de octei fa de nceputul fiierului
Scriei o funcie care determin numrul de octei ai unui fiier.
#include
long FileSize(FILE *pf)
{ long pozv, noct;
pozv = ftell(pf); /* salveaza pozitia curenta */
fseek(pf, 0L, SEEK_END); /* pozitionare la sfarsit */
noct = ftell(pf); /* numar de octeti din fisier */
fseek(pf, pozv, SEEK_SET); /*revenirea la pozitia veche*/
return noct;
} tratarea erorilorint feof(FILE *pf);
ntoarce o valoare diferit de 0, dac s-a detectat marcajul de sfrit de fiier
int ferror(FILE *pf);
ntoarce o valoare diferit de 0, dac s-a detectat o eroare n cursul operaiei de intrare / ieire
Fiierul comenzi.dat conine articole structuri cu cmpurile:
-denumire produs- un ir de 20 de caractere
-cantitate comandat o valoare real.
Fiierul depozit.dat este format din articole avnd cmpurile:
- denumire produs un ir de 20 de caractere
- stoc i stoc_minim valori reale
- pre unitar valoare real
S se actualizeze fiierul de stocuri, prin onorarea comenzilor. O comand este onorat, dac prin satisfacerea ei, stocul rmas n magazie nu scade sub stocul minim.
Se va creea un fiier facturi.dat, coninnd pentru fiecare comand onorat, denumirea produsului comandat i valoarea comenzii.
Se vor crea de asemeni dou fiiere, unul cu comenzi care nu au fost satisfcute, deoarece produsele erau n cantiti insuficiente, cellalt cu comenzi de produse care nu exist n depozit.
#include
#include
typedef struct { char den[20];
double cant;} comanda;
typedef struct { char den[20];
double stoc, stoc_min, pret;} depozit;
typedef struct { char den[20];
double val;} factura;
void main(void)
{ comanda com;
depozit dep;
factura fac;
double t;
int gasit, eof;
FILE *fc, *fd, *ff, *fc1, *fc2;
/* deschidere fisiere */
if((fc=fopen(comenzi.dat,rb))==NULL){
fprintf(stderr,eroare deschidere comenzi\n);
exit(1);
};
if((fd=fopen(depozit.dat,r+b))==NULL){
fprintf(stderr,eroare deschidere depozit\n);
exit(1);
};
ff=fopen(facturi.dat,wb);
fc1=fopen(com1.dat,wb);
fc2=fopen(com2.dat,wb);
while(1) { /* ciclu procesare comenzi */
if(!fread(&com, sizeof(com), 1, fc) break;
gasit=0;
rewind(fd);
do {
eof=fread(&dep, sizeof(dep), 1, fd)==0;
if(!eof) {
if(strcmp(com.den, dep.den)==0){
gasit = 1;
if((t=dep.stoc com.cant)>=dep.stoc_min) {
dep.stoc=t;
fseek(fd, -sizeof(dep), SEEK_CUR);
fwrite(&dep, sizeof(dep), 1, fd);
fac.val=com.cant * dep.pret;
strcpy(fac.den, com.den);
fwrite(&fac, sizeof(fac), 1, ff);
}
else
fwrite(&com, sizeof(com), 1, fc1);
break;
}
}
} while(!gasit && !eof);
if(!gasit)
fwrite(&com, sizeof(com), 1, fc2);
}
fclose(fc);
fclose(fd);
fclose(ff);
fclose(fc1);
fclose(fc2);
}
SemnturEfect
FILE* fopen(char* nume, char* mod);deschide fiierul; ntoarce pointerul la fiierul deschis sau NULL dac operaia eueaz
int fclose(FILE* pf);nchide fiierul
int fgetc(FILE* pf);citete 1 caracter din fiier ntoarce caracterul citit sau EOF
int fputc(char c, FILE* pf);scrie caracterul n fiier
char* fgets(char* s, int n, FILE* pf);citete din fiier n s cel mult n-1 caractere,sau pn la ntlnire \n, n locul cruia pune \0. ntoarce s sau NULL, dac s-a citit EOF.
int fputs(char* s, FILE* pf);copiaz irul n fiierul de ieire.nlocuiete terminatorul \0 cu \n.
int fscanf(FILE* pf, char* format, lista_adrese);citire din fiier sub controlul formatului. ntoarce numrul de cmpuri citite sau EOF, n caz de eroare sau sfrit de fiier.
int fprintf(FILE* pf, char* format, lista_expresii);scriere n fiier sub controlul formatului. ntoarce numrul de caractere scrise sau valoare negativ n caz de eroare.
int fread(char* zona, int la, int na, FILE* pf);citete din fiier n zona, na articole de lungime la fiecare.ntoarce numrul de articole efectiv citite.
int fwrite(char* zona, int la, int na, FILE* pf);scrie n fiier din zona, na articole de lungime la fiecare.ntoarce numrul de articole efectiv scrise.
int fseek(FILE* pf, long depl, int orig);poziionare cu depl octei fa de nceput, poziia curent sau sfritul fiierului
void rewind(FILE* pf);poziionare la nceputul fiierului
long ftell(FILE* pf);determin poziia curent n fiier.
int feof(FILE* pf);ntoarce nenul dac s-a detectat sfrit de fiier
int ferror(FILE* pf);ntoarce nenul dac s-a detectat o eroare n cursul operaiei de intrare / ieire
Fiiere n C++.
Realizarea funciilor de intrare/ieire n C++ se realizeaz prin intermediul fluxurilor (streamuri). Un flux este o clas.
Fluxurile pot fi clasificate n:
fluxuri de intrare/ieire standard
fluxuri de intrare/ieire folosind fiiere
fluxuri de intrare/ieire n memorie
n instruciunea cout .
Obiectele cin i cout sunt declarate n iostream.h.
Utilizatorul i definete propriile fluxuri, declarndu-le ca obiecte n clasele:
ofstream., pentru operaii de scriere
ifstream, pentru operaii de citire
fstream, pentru operaii att de citire, ct i de scriere
Pentru a folosi aceste clase trebuie inclus fiierul antet fstream.h .
Deschiderea unui fiier (asocierea fiier stream) se face cu funcia membru open(), avnd semntura:
void open(char* numefisier, int mod, int acces);
Modul n care poate fi deschis un fiier este precizat n clasa ios prin enumeratorii:
in
- fiierul se deschide pentru citire; fiierul trebuie s existe
out
- fiierul se deschide pentru scriere; dac exist se terge i se creaz un nou fiier
ate
- fiierul se deschide pentru adugare la sfrit, dac nu exist se creaz
app
- fiierul se deschide pentru adugare la sfrit; fiierul trebuie s existe
trunc
- dac fiierul exist, va fi ters i se va crea un fiier nou pentru scriere
nocreate- fiierul deschis trebuie s existe (el nu poate fi creat)
noreplace- fiierul este deschis, iar coninutul lui nu poate fi nlocuit
binary- fierul deschis va fi prelucrat ca un fiier binar
ifstream f;
f.open(note.dat, ios::in);
Modul de acces poate specifica una din valorile:
0 fiier fr restricii de acces
1 fiier protejat la scriere
2 fiier ascuns
4 fiier sistem
8 fiier arhiv
Desfacerea legturii fiier stream se face folosind funcia close().
Dac n urma deschiderii fiierului, variabila stream este egal cu NULL, atunci operaia de deschidere a euat.
ifstream f;
if(!f.open(note.dat, ios::in)){
cerr