Sunteți pe pagina 1din 17

INFORMATIC*I*

IB.11. Operaii cu fiiere n limbajul C

Capitolul IB.11. Operaii cu fiiere n limbajul C


Cuvinte cheie
Fiiere text, fiiere binare,
deschidere/ nchidere fiiere, citire-scriere fiiere,
acces direct, fiiere predefinite, funcia fflush, redirectarea fiierelor
standard, fiiere n C++

IB.11.1. Noiunea de fiier


Un fiier este o colecie de date memorate pe un suport extern i care este identificat
printr-un nume.
Coninutul fiierelor poate fi foarte variat:
texte, inclusiv programe surs
numere
alte informaii binare: programe executabile, numere n format binar, imagini sau sunete
codificate numeric .a.
Numrul de elemente ale unui fiier este variabil (poate fi nul).
Fiierele de date se folosesc pentru:
date iniiale mai numeroase
rezultate mai numeroase
pstrarea permanent a unor date de interes pentru anumite aplicaii.
Fiierele sunt entiti ale sistemului de operare i ca atare ele au nume care respect conveniile
sistemului, fr legtur cu un anume limbaj de programare. Operaiile cu fiiere sunt realizate de
ctre sistemul de operare, iar compilatorul unui limbaj traduce funciile de acces la fiiere n apeluri
ale funciilor de sistem.
De obicei prin fiier se subnelege un fiier disc (pe suport magnetic sau optic), dar noiunea de
fiier este mai general i include orice flux de date din exterior spre memorie sau dinspre memoria
intern spre exterior. De aceea s-a introdus cuvntul stream, tradus prin flux de date si sinonim cu
fiier logic, deci orice surs sau destinaie extern a datelor.
Stream (flux de date, canal) este n acest context sinonim cu file (fiier): pune accent pe aspectul
dinamic al transferului de date.
Programatorul se refer la un fiier printr-o variabil; tipul acestei variabile depinde de limbajul
folosit i chiar de funciile utilizate (n C). Asocierea dintre numele extern (un ir de caractere) i
variabila din program se face la deschiderea unui fiier, printr-o funcie standard.
IB.11.2. Tipuri de fiiere n C
Fiiere text
conin o succesiune de linii, separate prin NewLine
fiecare linie are 0 sau mai multe caractere tipribile i/sau tab
Fiiere binare
conin o succesiune de octei
-1-

INFORMATIC*I*

IB.11. Operaii cu fiiere n limbajul C

Un fiier text conine numai caractere ASCII, grupate n linii de lungimi diferite, fiecare linie
terminat cu unul sau dou caractere terminator de linie.
Caracter terminator de linie:
fiierele Unix/Linux: un singur caracter terminator de linie \n
fiierele Windows i MS-DOS: caracterele \r i \n (CR,LF) ca terminator de
linie
Un fiier text poate fi terminat printr-un caracter terminator de fiier (Ctrl-Z = EOF )
Valoarea efectiv este dependent de sistem, dar n general este -1.
Acest terminator nu este ns obligatoriu. Sfritul unui fiier disc poate fi detectat i pe baza
lungimii fiierului (numr de octei), memorat pe disc.
Funciile de citire sau de scriere cu format din/n fiiere text realizeaz conversia automat din
format extern (ir de caractere) n format intern (binar virgul fix sau virgul mobil) la citire i
conversia din format intern n format extern, la scriere pentru numere ntregi sau reale.
Fiierele binare pot conine:
numere n reprezentare intern (binar)
articole (structuri de date)
fiiere cu imagini grafice, n diverse formate, etc
Citirea i scrierea se fac fr conversie de format.
Pentru fiecare tip de fiier binar este necesar un program care s cunoasc i s interpreteze corect
datele din fiier (structura articolelor). Este posibil ca un fiier binar s conin numai caractere, dar
funciile de citire i de scriere pentru aceste fiiere nu cunosc noiunea de linie; ele specific
numrul de octei care se citesc sau se scriu.
Consola i imprimanta sunt considerate fiiere text.
Fiierele disc trebuie deschise i nchise, dar fiierele consol i imprimanta nu trebuie
deschise i nchise.
IB.11.3. Operarea cu fiiere
Pentru operarea cu un fiier (text sau binar) se definete o variabil de tip FILE * pentru accesarea
fiierului:
FILE * - tip structur definit n stdio.h
Conine informaii referitoare la fiier i la tamponul de transfer de date ntre memoria central i
fiier:
adresa
lungimea tamponului
modul de utilizare a fiierului
indicator de sfrit de fiier
indicator de poziie n fiier

-2-

INFORMATIC*I*

IB.11. Operaii cu fiiere n limbajul C

Etapele pentru operarea cu un fiier n limbajul C sunt:


se deschide fiierul pentru un anumit mod de acces, folosind funcia de biblioteca
fopen,
o realizeaz i asocierea ntre variabila fiier i numele extern al fiierului
se prelucreaz fiierul
o operaii citire/scriere
se nchide fiierul folosind funcia de biblioteca fclose.
IB.11.4. Funcii pentru deschidere i nchidere fiiere
Funciile standard pentru acces la fiiere sunt declarate n stdio.h. Dup cum spuneam mai devreme,
funciile de citire/scriere/pozitionare n fiier folosesc pentru identificarea unui fiier o variabil
pointer la o structur predefinit FILE.
IB.11.4. 1 Deschiderea unui fiier
Pentru a citi sau scrie dintr-un/ntr-un fiier disc, acesta trebuie mai nti deschis folosind funcia
fopen.
FILE *fopen (const char *numefisier, const char *mod);
Deschide fiierul cu numele dat pentru acces de tip mod
Returneaz pointer la fiier sau NULL dac fiierul nu poate fi deschis
Valoarea returnat este memorat n variabila fiier, care a fost declarat (FILE *)
pentru accesarea lui.
unde:
numefisier: numele fiierului
mod: ir de caractere (ntre 1 i 3 caractere):
r - readonly , este permis doar citirea dintr-un fiier existent
w - write, creaz un nou fiier, sau dac exist deja, distruge vechiul coninut
a - append, deschide pentru scriere un fiier existent (scrierea se va face n
continuarea informaiei deja existente n fiier, deci pointerul de acces se plaseaz la
sfritul fiierului)
+ - permite scrierea i citirea din acelasi fiier - actualizare (ex: "r+", "w+", "a+").
t sau b - tip fiier ("text", "binary"), implicit este t
Primul argument al funciei fopen este numele extern al fiierului scris cu respectarea conveniilor
limbajului C.
Numele fiier extern poate include urmtoarele:
Numele unitii de disc sau partiiei disc ( ex: A:, C:, D:, E:)
Calea spre fiier: succesiune de nume de fiiere catalog (director), separate printr-un
caracter ('\' n MS-DOS i MS-Windows, sau '/' n Unix i Linux)
Numele propriu-zis al fiierului
Extensia, care indic tipul fiierului i care poate avea ntre 0 i 3 caractere n MSDOS.
Sistemele MS-DOS i MS-Windows nu fac deosebire ntre litere mari i litere mici, n cadrul
numelor de fiiere.
Atenie! pentru separarea numelor de cataloage dintr-o cale se vor folosi:
-3-

INFORMATIC*I*

IB.11. Operaii cu fiiere n limbajul C

\\ - pentru a nu se considera o secven de caractere escape sau:


caracterul /
Exemple:
char *numef = "C:\\WORK\\T.TXT";
char *numef = c:/work/t.txt;

La deschiderea unui fiier se iniializeaz variabila pointer asociat, iar celelalte funcii se refer la
fiier numai prin intermediul variabilei pointer.
Funcia fopen are rezultat NULL (0) dac fiierul specificat nu este gsit dup cutare n directorul
curent sau pe calea specificat.
Exemplu:
//exemplu 1
char *numef = "C:\\WORK\\T.TXT"; // sau c:/work/t.txt
FILE * f;
// pentru referire la fiier
if ( (f=fopen(numef,"r")) == NULL) {
printf("Eroare la deschidere fiier %s \n", numef);
return;
}
//exemplu 2
#include <stdio.h>
int main ( ) {
FILE * f; // pentru referire la fiier
// deschide un fiier binar ptr citire
f = fopen ( c:\\t.txt", "rb );
printf ( f == NULL ? "Fiier negasit" : " Fiier gasit");
...
if (f)
// dac fiier existent
fclose(f); // nchide fiier
return 0;
}

Diferena dintre b i t este aceea c la citirea dintr-un fiier binar toi octeii sunt considerai ca date
i sunt transferai n memorie, iar la citirea dintr-un fiier text anumii octei sunt interpretai ca
terminator de linie (\0x0a) sau ca terminator de fiier (\0x1a). Nu este obligatoriu ca orice fiier text
s se termine cu un caracter special cu semnificaia sfrit de fiier (CTRL-Z , de exemplu) .
Pentru fiierele text sunt folosite modurile:
w pentru crearea unui nou fiier
r pentru citirea dintr-un fiier
a pentru adugare la sfritul unui fiier existent
Modul w+ poate fi folosit pentru citire dup creare fiier.
Deschiderea n modul w terge orice fiier existent cu acelai nume, fr avertizare, dar
programatorul poate verifica existena unui fiier n acelai director nainte de a crea unul nou.
Pentru fiierele binare se practic actualizarea pe loc a fiierelor, fr inserarea de date ntre cele
existente, deci modurile r+, a+, w+. (literele r i w nu pot fi folosite simultan).
-4-

INFORMATIC*I*

IB.11. Operaii cu fiiere n limbajul C

Fiierele standard de intrare-ieire (tastatura i ecranul consolei) au asociate variabile de tip pointer
cu nume predefinit (stdin i stdout); care pot fi folosite n funciile destinate tuturor fisierelor, cum
ar fi fflush.
Pentru nchiderea unui fiier disc se folosete funcia fclose:
int fclose(FILE *fp);
nchide fiierul i elibereaz zona tampon
n caz de succes ntoarce 0, altfel, ntoarce EOF.

nchiderea este absolut necesar pentru fiierele n care s-a scris ceva, dar poate lipsi dac s-au fcut
doar citiri din fiier.
IB.11.4. Operaii uzuale cu fiiere text
Accesul la fiiere text se poate face
fie la nivel de linie
fie la nivel de caracter
dar numai secvenial.
Deci nu se pot citi/scrie linii sau caractere dect n ordinea memorrii lor n fiier i nu pe srite
(aleator)!
Nu se pot face modificri ntr-un fiier text fr a crea un alt fiier, deoarece nu sunt de conceput
deplasri de text n fiier!
Pentru citire/scriere din/n fiierele standard stdin/stdout se folosesc funcii cu nume puin diferit i
cu mai puine argumente, dar se pot folosi i funciile generale destinate fiierelor disc. Urmeaz
cteva perechi de funcii:
Sintaxa
Descriere
Citete un caracter din f i l ntoarce ca un
int fgetc (FILE * f);
unsigned char convertit la int,
// sau getc (FILE*)
Returneaz EOF dac s-a ntlnit sfritul de
fiier sau n caz de eroare.

int fputc (int c, FILE * f);


// sau putc (int, FILE*)

Scrie caracterul cu codul ascii c n fiier

char * fgets( char * line, int max, FILE Citete maxim n-1 caractere sau pn la \n
inclusiv, i le depune n s, adaug la sfrit \0 dar
*f);
nu elimin terminatorul de linie \n. Returneaz
adresa irului.
La eroare ntoarce valoarea NULL.

int fputs (char * line, FILE *f);

Scrie irul line n fiier, fr caracterul '\0'.


La eroare ntoarce EOF.

Detectarea sfritului de fiier se poate face i cu ajutorul funciei feof (Find End of File):
int feof ( FILE *fp);
-5-

INFORMATIC*I*

IB.11. Operaii cu fiiere n limbajul C

testeaz dac s-a ajuns la end-of-file al fiierului referit de fp


returneaz 0 dac nu s-a detectat sfrit de fiier la ultima operaie de citire, respectiv
o valoare nenul (adevarat) pentru sfrit de fiier.
Atenie! Rezultatul lui feof se modific dup ncercarea de a citi dup sfritul fiierului!
Se va scrie n fiierul de ieire i 1, rezultatul ultimului apel al funciei fgetc:
while ( ! feof(f1))
fputc(fgetc(f1),f2);

Soluia preferabil pentru ciclul de citire-scriere caractere este urmtoarea:


while ( (ch=fgetc(f1)) != EOF)
fputc ( ch, f2);

Exemplu:
// citire i afiare linii dintr-un fiier
#include<stdio.h>
#include<stdlib.h>
int main()
{
FILE *fp;
char s[80];
if ( (fp=fopen("c:\\test.c","r")) == NULL ) {
printf ( "Nu se poate deschide la citire fiierul!\n );
exit (1);
}
while ( fgets(s,80,fp) != NULL )
printf ( "%s", s);
fclose (fp);
return 0;
}
/*
Scriere sub form de litere mici caracterele dintr-un fiier n alt fiier
numele sursei i destinaiei transmise n linia de comand.
Lansarea n execuie a programului:
copiere fiier_sursa.dat fiier_dest.dat
*/
#include<stdio.h>
#include<ctype.h>
int main(int argc, char** argv){
FILE * f1, * f2; int ch;
f1= fopen (argv[1], "r");
f2= fopen (argv[2], "w");
if ( f1==0 || f2==0) {
puts (" Eroare la deschidere fiiere \n");

-6-

INFORMATIC*I*

IB.11. Operaii cu fiiere n limbajul C

return 1;
}
while ( (ch=fgetc(f1)) != EOF)
fputc ( tolower(ch),f2);
fclose(f1);
fclose(f2);
return 0;

// citeste din f1
// scrie n f2

n principiu se poate citi integral un fiier text n memorie, dar n practic se citete o singur linie
sau un numr de linii succesive, ntr-un ciclu repetat pn se termin fiierul (pentru a se putea
prelucra fiiere orict de mari).
Pentru actualizarea unui fiier text prin modificarea lungimii unor linii, tergerea sau inseria de
linii se va scrie un alt fiier i nu se vor opera modificrile direct pe fiierul existent.
IB.11.5. Intrri/ieiri cu conversie de format
Datele numerice pot fi scrise n fiiere disc fie n format intern (mai compact), fie transformate n
iruri de caractere (cifre zecimale, semn .a).
Un fiier text ocup mai mult spaiu deoarece formatul ir de caractere necesit i caractere
separator ntre numere. Avantajul este c un fiier text poate fi citit cu programe scrise n orice
limbaj sau cu orice editor de texte sau cu alt program utilitar de vizualizare fiiere!
Funciile de citire-scriere cu conversie de format i editare sunt:
int fscanf (FILE * f, char * fmt, ...)
realizeaz citirea cu format dintr-un fiier; analog scanf
int fprintf (FILE * f, char * fmt, ...)
identic cu printf cu deosebirea c scrie ntr-un fiier

Pentru aceste funcii se aplic toate regulile de la funciile scanf i printf.


Un fiier text prelucrat cu funciile fprintf i fscanf conine mai multe cmpuri de date separate ntre
ele prin unul sau mai multe spaii albe (blanc, tab, linie nou). Coninutul cmpului de date este
scris i interpretat la citire conform specificatorului de format pentru acel cmp.
Exemplu de creare i citire fiier de numere:
FILE * f;
int x;
// creare fiier de date:
f = fopen("num.txt", "w");
for (x=1;x<=100;x++)
fprintf(f,"%4d", x);
fclose(f);

// f = pointer la fiier

// deschide fiier
// scrie un numar
// inchidere fiier

// citire i afiare fiier creat:


f=fopen("num.txt", "r");
if ( (f == NULL ) {
printf ( "Nu se poate deschide la citire fiierul!\n );
exit (1);
}

-7-

INFORMATIC*I*
while (fscanf(f,"%d", &x) == 1)
printf("%4d", x);

IB.11. Operaii cu fiiere n limbajul C


// pana la sfirsit fiier
// afiare numar citit

Exemplu:
ntr-un fiier de tip text sunt pstrate valorile reale ale unei msuratori sub forma:
nr_msuratori
val1
val2
val3 ...
S se scrie programul care afieaz numrul de msurtori i valorile respective.
Se vor aduga la fiier noi msuratori pn la introducerea valorii 0.
Rezolvare:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define MAX 100
void afiseaza(double *mas,int nrm){
int i;
for (i=0; i<nrm; i++)
printf ("Masuratoarea %d = %6.2e\n", i+1, mas[i]);
}
void loadmas (FILE *fp, int *nrm, double *mas){
int i=0;
fscanf (fp,"%d", nrm);
if (*nrm>MAX) *nrm = MAX;
for ( ; i<*nrm; i++)
fscanf (fp, "%lf", &mas[i]);
}
int main(){
FILE *fp;
double masur[MAX], mas_noua=1;
char nume_fis[12];
int nr_mas;
printf ("nume fisier:");
gets (nume_fis);
if ( (fp = fopen(nume_fis, "r+") ) == 0 ){
printf ("nu exista fisierul\n");
exit (1);
}
loadmas (fp,&nr_mas,masur);
afiseaza (masur,nr_mas);
fclose(fp);
if ( (fp = fopen(nume_fis, a") ) == 0 ){
printf ("nu exista fisierul\n");
exit (1);

-8-

INFORMATIC*I*

IB.11. Operaii cu fiiere n limbajul C

}
printf ("\nmasuratori noi:\n);
while( nr_mas++<MAX-1){
scanf(%lf,&mas_noua);
if(mas_noua) fprintf (fp, "%lf\n", mas_noua);
else break;
}
fclose(fp);
if ( (fp = fopen(nume_fis, "r+") ) == 0 ){
printf ("nu exista fisierul\n");
exit (1);
}
fprintf (fp, "%d", --nr_mas);
fclose (fp);
return 0;
}

IB.11.6. Funcii de citire-scriere pentru fiiere binare


Un fiier binar este format n general din articole de lungime fix, fr separatori ntre
articole. Un articol poate conine:
un singur octet
un numr binar (pe 2, 4 sau 8 octei)
structur cu date de diferite tipuri
Funciile de acces pentru fiiere binare fread i fwrite pot citi sau scrie unul sau mai multe articole,
la fiecare apelare. Transferul ntre memorie i suportul extern se face fr conversie sau editare
(adugare de caractere la scriere sau eliminare de caractere la citire). Prototipuri funcii intrare/iesire
(fiiere binare b):
size_t fread (void *ptr, size_t size, size_t nmemb, FILE *fp)
Citete la adresa ptr cel mult nmemb elemente de dimensiune size din fiierul referit de fp
size_t fwrite (void *ptr, size_t size, size_t nmemb, FILE *fp)
Scrie n fiierul referit de fp cel mult nmemb elemente de dimensiune size de la adresa ptr

Exemple:
int a[10];
fread (a, sizeof(int), 10, fp);
fwrite(a, sizeof(int),10,fp);

De remarcat c primul argument al funciilor fread i fwrite este o adres de memorie (un pointer):
adresa unde se citesc date din fiier sau de unde se iau datele scrise n fiier.
Al doilea argument este numrul de octei pentru un articol, iar al treilea argument este numrul de
articole citite sau scrise. Numrul de octei citii sau scrii este egal cu produsul dintre lungimea
unui articol i numrul de articole.
-9-

INFORMATIC*I*

IB.11. Operaii cu fiiere n limbajul C

Rezultatul funciilor este numrul de articole efectiv citite sau scrise i este diferit de argumentul 3
numai la sfrit de fiier (la citire) sau n caz de eroare de citire/scriere!
Dac tim lungimea unui fiier i dac este loc n memoria RAM atunci putem citi un ntreg fiier
printr-un singur apel al funciei fread sau putem scrie integral un fiier cu un singur apel al funciei
fwrite. Citirea mai multor date dintr-un fiier disc poate conduce la un timp mai bun fa de
repetarea unor citiri urmate de prelucrri, deoarece se pot elimina timpii de ateptare pentru
poziionarea capetelor de citire scriere pe sectorul ce trebuie citit (rotaie disc plus comand
capete).
Programul urmtor scrie mai multe numere ntregi ntr-un fiier disc (unul cte unul) i apoi citete
coninutul fiierului i afieaz pe ecran numerele citite.
int main () {
FILE * f; int x; char * numef =num.bin;
// creare fiier
f=fopen(numef,"wb"));
// fisier in directorul curent
for (x=1; x<=100; x++)
fwrite (&x,sizeof(float),1,f);
fclose(f);
// citire fiier pentru verificare
if ( (f=fopen(numef,"rb")) == NULL ) { // fisier in directorul curent
printf ( "Nu se poate deschide la citire fiierul!\n );
exit (1);
}
printf("\n");
while (fread (&x,sizeof(float),1,f)==1)
printf ("%4d ",x);
fclose(f);
return 0;
}

Lungimea fiierului num.bin este de 200 de octei, cte 2 octei pentru fiecare numr ntreg, n timp
ce lungimea fiierului num.txt creat anterior cu funcia fprintf este de 400 de octei (cte 4 caractere
ptr fiecare numr). Pentru alte tipuri de numere diferena poate fi mult mai mare.
De obicei articolele unui fiier au o anumit structur, n sensul c fiecare articol conine mai multe
cmpuri de lungimi i tipuri diferite. Pentru citirea sau scrierea unor astfel de articole n program
trebuie s existe (cel puin) o variabil structur care s reflecte structura articolelor.
Exemplu de definire a structurii articolelor unui fiier simplu cu date despre elevi i a funciilor ce
scriu sau citesc articole ce corespund unor variabile structur:
typedef struct {
char nume[25];
float medie;
} Elev;
// creare fiier cu nume dat
void creare(char * numef) {
FILE * f; Elev s;
f=fopen(numef,"wb");
printf ("Nume i medie ptr. fiecare student: \n");
while (scanf ("%s %f ", s.nume, &s.medie) != EOF)
fwrite(&s,sizeof(s),1,f);
fclose (f);
}

- 10 -

INFORMATIC*I*

IB.11. Operaii cu fiiere n limbajul C

// afiare coninut fiier pe ecran


void listare (char* numef) {
FILE * f; Elev e;
if ( (f=fopen(numef,"rb")) == NULL ) { // fisier in directorul curent
printf ( "Nu se poate deschide la citire fiierul!\n );
exit (1);
}
while (fread (&e,sizeof(e),1,f)==1)
printf ("%-25s %6.2f \n",e.nume, e.medie);
fclose (f);
}
// adaugare articole la sfritul unui fiier existent
void adaugare (char * numef) {
FILE * f; Elev e;
if ( (f=fopen(numef,"ab")) == NULL ) { // fisier in directorul curent
printf ( "Nu se poate deschide la citire fiierul!\n );
exit (1);
}
printf ("Adaugare nume i medie:\n");
while (scanf ("%s%f", e.nume, &e.medie) != EOF)
fwrite (&e, sizeof(e), 1, f);
fclose (f);
}

IB.11.7. Funcii pentru acces direct la datele dintr-un fiier


Accesul direct la date dintr-un fiier este posibil numai pentru un fiier cu articole de lungime fix
i nseamn posibilitatea de a citi sau scrie oriunde ntr-un fiier, printr-o poziionare prealabil
nainte de citire sau scriere. Fiierele mari care necesit regsirea rapid i actualizarea frecvent de
articole vor conine numai articole de aceeai lungime.
n C poziionarea se face pe un anumit octet din fiier, iar funciile standard permit accesul direct la
o anumit adres de octet din fiier. Funciile pentru acces direct din stdio.h permit operaiile
urmtoare:
Poziionarea pe un anumit octet din fiier (fseek).
Citirea poziiei curente din fiier (ftell).
Memorarea poziiei curente i poziionare (fgetpos, fsetpos).
Poziia curent n fiier este un numr de tip long, pentru a permite operaii cu fiiere foarte lungi.
Poziia se obine printr-un apel al funciei ftell:
long int ftell (FILE *fp)
ntoarce valoarea indicatorului de poziie
pentru fiier binar: numrul de octei de la nceputul fiierului
pentru fiier text: o valoare ce poate fi utilizat de fseek pentru a seta indicatorul de poziie n
fiier la aceast poziie.

Funcia fseek are prototipul urmtor :


int fseek (FILE *fp, long int offset, int poziie)
poziioneaz indicatorul de poziie la valoarea dat de offset fa de:
SEEK_SET sau 0 nceputul fiierului
- 11 -

INFORMATIC*I*

IB.11. Operaii cu fiiere n limbajul C

SEEK_CUR sau 1 poziia curent


SEEK_END sau 2 sfritul fiierului

Offset reprezint numrul de octei fa de punctul de referin.


Exemple:
poziionarea la sfritul fiierului: fseek (fp, 0, SEEK_END)
poziionarea la caracterul precedent: fseek (fp, -1, SEEK_CUR)
poziionarea la inceputul fiierului: fseek (fp, 0, SEEK_SET)
Atenie! Poziionarea relativ la sfritul unui fiier nu este garantat nici chiar pentru fiiere binare,
astfel c ar trebui evitat!
Ar trebui evitat i poziionarea fa de poziia curent cu o valoare negativ, care nu funcioneaz
n toate implementrile!
Funcia fseek este util n urmtoarele situaii:
Pentru repoziionare pe nceput de fiier dup o cutare i nainte de o alt cutare
secvenial n fiier (fr a nchide i a redeschide fiierul)
Pentru poziionare pe nceputul ultimului articol citit, n vederea scrierii noului coninut
(modificat) al acestui articol, deoarece orice operaie de citire sau scriere avanseaz automat
poziia curent n fiier, pe urmtorul articol.
Pentru acces direct dup coninutul unui articol (dup un cmp cheie), dup ce s-a calculat
sau s-a gsit adresa unui articol cu cheie dat.
ntr-un fiier text poziionarea este posibil numai fa de nceputul fiierului, iar poziia se obine
printr-un apel al funciei ftell.
Modificarea coninutului unui articol (fr modificarea lungimii sale) se face n mai muli pai:
Se caut articolul ce trebuie modificat i se reine adresa lui n fiier (nainte sau dup citirea
sa);
Se modific n memorie articolul citit;
Se readuce poziia curent pe nceputul ultimului articol citit;
Se scrie articolul modificat, peste coninutul su anterior.
Exemplu de secven pentru modificarea unui articol:
pos=ftell (f);
fread (&e,sizeof(e),1,f );
// poziia inainte de citire
. . .
// modifica ceva in variabila e
fseek (f,pos,0);
// repoziionare pe articolul citit
fwrite (&e,sizeof(e),1,f);
// rescrie ultimul articol citit

Memorarea poziiei curente sau poziionarea se pot realiza utiliznd urmtoarele funcii:
int fgetpos (FILE *fp, fpos_t *poziie)
memoreaz starea curent a indicatorului de poziie al fluxului referit de fp n poziie;
ntoarce 0 dac operaia s-a realizat cu succes!
int fsetpos (FILE *fp, const fpos_t *poziie)
seteaz indicatorul de poziie al fluxului referit de fp la valoarea data de poziie
void rewind (FILE *fp)
seteaz indicatorul de poziie al fluxului referit de fp la nceputul fiierului
- 12 -

INFORMATIC*I*

IB.11. Operaii cu fiiere n limbajul C

Exemplu:
Funcie care modific coninutul mai multor articole din fiierul de elevi creat anterior.
// modificare coninut articole, dupa cautarea lor
void modificare (char * numef) {
FILE * f;
Elev e;
char nume[25];
long pos;
int ef;
if ( (f=fopen(numef,"rb+")) == NULL ) {// fisier in directorul curent
printf ( "Nu se poate deschide la citire fiierul!\n );
exit (1);
}
do {
printf ("Nume cautat: ");
scanf ("%s",nume);
if (strcmp(nume, .) == 0)

break; // datele se termin cu un punct

// cauta "nume" n fiier


fseek (f, 0, 0);
// readucere pe inceput de fiier
while ( (ef=fread (&e, sizeof(e), 1, f)) ==1 )
if (strcmp (e.nume, nume)==0) {
pos= ftell(f) - sizeof(e);
break;
}
if ( ef < 1) break;
printf ("noua medie: ");
scanf ("%f", &e.medie);
fseek (f, pos, 0);
// pozit. pe inceput articol gasit
fwrite (&e, sizeof(e), 1, f); // rescrie articol modificat
} while (1);
fclose (f);
}
int main(){
char name[]="c:elev.txt;
creare (name);
listare (name);
adaugare (name);
modificare (name);
listare (name);
return 0;
}

- 13 -

INFORMATIC*I*

IB.11. Operaii cu fiiere n limbajul C

IB.11.8. Fiiere predefinite


Exist trei fluxuri predefinite, care se deschid automat la lansarea unui program:
stdin - fiier de intrare, text, este intrarea standard - tastatura
stdout - fiier de ieire, text, este ieirea standard - ecranul monitorului.
stderr - fiier de iesire, text, este ieirea standard de erori - ecranul monitorului.
Ele pot fi folosite n diferite funcii, un exemplu practic este funcia fflush care golete zona tampon
(buffer) asociat unui fiier.
Observaii
Nu orice apel al unei funcii de citire sau de scriere are ca efect imediat un transfer de date
ntre exterior i variabilele din program!
Citirea efectiv de pe suportul extern se face ntr-o zon tampon asociat fiierului, iar
numrul de octei care se citesc depind de suport: o linie de la tastatur, unul sau cteva
sectoare disc dintr-un fiier disc, etc.
Cele mai multe apeluri de funcii de I/E au ca efect un transfer ntre zona tampon (anonim) i
variabilele din program.
Este posibil ca s existe diferene n detaliile de lucru ale funciilor standard de citire-scriere
din diferite implementri (biblioteci), deoarece standardul C nu precizeaz toate aceste detalii!
Funcia fflush
Are rolul de a goli zona tampon folosit de funciile de I/E, zon altfel inaccesibil programatorului
C. Are ca argument variabila pointer asociat unui fiier la deschidere, sau variabilele predefinite
stdin i stdout.
fflush (FILE* f);
Exemple de situaii n care este necesar folosirea funciei fflush:
Citirea unui caracter dup citirea unui cmp sau unei linii cu scanf :
int main () {
int n;
char s[30];
char c;
scanf (%d,&n);
// fflush(stdin);

// sau scanf(%s,s);
// pentru corectare

c = getchar();
printf (%d \n,c);
return 0;

// sau scanf (%c, &c);


// afiseaza codul lui c

}
/* va afia 10 care este codul numeric al caracterului terminator de
linie \n, n loc s
afieze codul caracterului c, deoarece dup o
citire cu scanf n zona tampon rmn unul sau cteva caractere
separator de cmpuri (\n, \t, ), care trebuie scoase de acolo
prin fflush(stdin) sau prin alte apeluri scanf. */

- 14 -

INFORMATIC*I*

IB.11. Operaii cu fiiere n limbajul C

Funcia scanf oprete citirea unei valori din zona tampon ce conine o linie la primul caracter
separator de cmpuri sau la un caracter ilegal n cmp (de ex. liter ntr-un cmp numeric)!
In cazul repetrii unei operatii de citire (cu scanf) dup o eroare de introducere n linia
anterioar (caracter ilegal pentru un anumit format de citire) n zona tampon rmn caracterele
din linie care urmau dup cel care a produs eroarea!
do {
printf ("x, y = ");
err = scanf ("%d%d", &x, &y);
if ( err == 2 ) break;
fflush (stdin);
} while (err != 2);

Observaie: Dup citirea unei linii cu funciile gets sau fgets nu rmne nici un caracter n
zona tampon i nu este necesar apelul lui fflush!
Se va folosi periodic fflush n cazul actualizrii unui fiier mare, pentru a evita pierderi de date
la producerea unor incidente (toate datele din zona tampon vor fi scrise efectiv pe disc):
int main () {
FILE * f;
int c;
char numef[]="TEST.DAT";
char x[ ] = "0123456789";
f=fopen (numef,"w");
for (c=0;c<10;c++)
fputc (x[c], f);
fflush (f);
// sau fclose(f);
f=fopen (numef,"r");
while ( (c=fgetc(f)) != EOF)
printf ("%c", c);
return 0;
}

IB.11.9. Redirectarea fiierelor standard


Trebuie observat c programele C care folosesc funcii standard de I/E cu consola pot fi folosite,
fr modificri, pentru preluarea de date din orice fiier i pentru trimiterea rezultatelor n orice
fiier, prin operaia numit redirectare (redirecionare) a fiierelor standard. Prin redirectare,
fiierele standard se pot asocia cu alte fiiere.
Redirectarea se face prin adugarea unor argumente n linia de comand la apelarea programului.
Exemplu:
fiier_exe < fiier_1

> fiier_2

n acest caz, preluarea informaiilor se face din fiier_1, iar afiarea informaiilor de ieire se face n
fiier_2.
Exemple:
- 15 -

INFORMATIC*I*

IB.11. Operaii cu fiiere n limbajul C

/*
* Copierea coninutului unui fiier n alt fiier utilizand redirectarea
* Folosind redirectarea fiierelor standard, se va lansa printr-o linie de
* comand de forma:
*
copiere1 <fiier_sursa.dat >fiier_dest.dat
* i atunci urmtorul program va avea acelai rezultat ca si cnd s-ar citi
* din fisier_sursa.dat
* i s-ar scrie n fiier_dest.dat
*/
#include <stdio.h>
int main(void){
char c;
while ( (c=getchar()) != EOF )
putchar(c);
return 0;
}
/*
* Exemplu de program filter:
* filter este numele unui program (fiier executabil) care aplic un filtru
* oarecare pe un text pentru a produce un alt text
* Folosind redirectarea fiierelor standard, se va lansa printr-o linie de
* comand de forma:
* filter <input - citire din input i scriere pe ecran
* filter >output - citire de la consola i scriere n output
* filter <input >output - citire din input i scriere n output
*/
#include <stdio.h>
// pentru funciile gets,puts
int main () {
char line[256];
while ( gets(line) != NULL)
if ( line[0]==/ && line[1]==/)
puts (line);
return 0;
}

//
//
//
//

aici se citete o linie


repeta citire linie
daca linie comentariu
atunci se scrie linia

Utilizarea comenzii filter fr argumente citete i afieaz la consol; utilizarea unui argument de
forma <input redirecteaz intrrile ctre fiierul input, iar un argument de forma >output
redirecteaz ieirile ctre fiierul output.
Redirectarea se poate aplica numai programelor care lucreaz cu fiiere text.

- 16 -

INFORMATIC*I*

IB.11. Operaii cu fiiere n limbajul C

IB.11.10. Anexa. Fiiere n C++


Fiierele sunt n C++ variabile de tipurile ifstream (input file stream), ofstream (output file stream)
sau fstream (care permit att citire ct i scriere din fiier).
Operaiile de citire/scriere se pot realiza fie prin funcii specifice, fie prin operatorii de inserie n
flux (<<) sau extragere din flux (>>). Pentru a putea fi folosite, fiierele disc trebuie deschise,
utiliznd funcia open i nchise dup folosire utiliznd funcia close.
Exemplu de scriere ntr-un fiier text:
ofstream ofile;
char nr[4];
ofile.open ("numere.txt");
for (int i=1;i<100;i++)
ofile << itoa (i,nr,10)<< endl;
ofile.close();

La citirea dintr-un fiier text exist dou diferene fa de scriere:


Trebuie detectat sfritul de fiier cu una din funciile eof(), good() sau bad().
Citirea cu operatorul >> repet ultima linie citit din fiier i de aceea se prefer funcia getline
(cu argument de tip string i nu vector de caractere).
Exemplu de citire din fiierul text creat anterior:
ifstream ifile; char nr[4];
ifile.open ("numere.txt");
while (ifile.good()) {
ifile >> nr;
cout << nr << endl;
}
ifile.close();

// while ( ! ifile.eof()) {

// poate lipsi

Se poate verifica dac deschiderea fiierului a reuit cu funcia is_open() :


if (! ifile.is_open()) cout << eroare la deschidere\n;

- 17 -

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