10. Prelucrarea fişierelor
10.1. Fişiere
În general, prin fişier înţelegem o colecţie ordonată de elemente numite înregistrări, care sunt păstrate pe diferite suporturi de memorie externă. Suportul de memorie externă cel mai folosit este suportul magnetic (de obicei discuri sub forma de flopy şi hardiscuri sau bandă magnetică care e din ce în ce mai rar folosită). Suportul magnetic este reutilizabil deoarece zona utilizată pentru a păstra înregistrările unui fişier poate fi ulterior reutilizată pentru a păstra înregistrările altui fişier.
Datele introduse de la un terminal se consideră că formează un fişier de intrare. Înregistrarea în acest caz, de obicei, este formată din datele tastate la terminal pe un rând deci caracterul de rând nou (newline) este terminator de înregistrare. În mod analog, datele care se afişează pe terminal formează un fişier de ieşire. Înregistrarea poate fi formată din caracterele unui rând.
Un fişier are o înregistrare care marchează sfârşitul de fişier. În cazul fişierelor de intrare de la tastatură sfârşitul de fişier se generează prin:
CTRL/Z
El poate fi pus în evidenţă folosind constanta simbolică EOF definită în fişierul stdio.h.
Prelucrarea fişierelor implică un număr de operaţii specifice acestora. Două operaţii sunt absolut necesare la prelucrarea oricărui fişier:
-
deschiderea fişierului;
-
închiderea fişierului.
Aceste operaţii de deschidere şi închidere a unui fişier se pot realiza prin intermediul unor funcţii speciale din biblioteca standard a limbajului C. Alte operaţii privind prelucrarea fişierelor sunt:
-
crearea unui fişier;
-
consultarea unui fişier;
-
actualizarea unui fişier;
-
adăugarea de înregistrări într-un fişier;
-
poziţionarea într-un fişier;
-
ştergerea unui fişier.
Prelucrarea fişierelor se poate face la două nivele. Primul nivel face apel direct la sistemul de operare şi se numeşte nivelul inferior de prelucrare al fişierelor. Cel de-al doilea nivel de prelucrare se realizează prin utilizarea unor proceduri specializate în prelucrarea fişierelor care, printre altele, pot rezerva şi gestiona automat zone tampon necesare realizării operaţiilor de intrare/ieşire, şi se numeşte nivelul superior de prelucrare al fişierelor
10.2. Nivelul inferior de prelucrare al fişierelor
La acest nivel de prelucrare se folosesc 5 funcţii:
-
open (creat)- pentru deschiderea fişierelor;
-
read - pentru citirea din fişier;
-
write - pentru citirea din fişier;
-
lseek - pentru poziţionarea în fişier;
-
close - pentru închiderea fişierului.
10.2.1. Deschiderea unui fişier
Orice fişier înainte de a fi prelucrat trebuie deschis. Această operaţie se realizează prin intermediul funcţiei open al cărui prototip este următorul:
int open (const char *cale, int acces);
unde:
-
cale este un pointer spre un şir de caractere care defineşte calea spre fişierul care se deschide (în cea mai simplă formă este numele fişierului dacă se află în directorul curent)
-
acces este o variabilă de tip întreg care poate lua una din valorile:
- O_RDONLY - fişierul se deschide numai în citire (consultare);
- O_WRONLY - fişierul se deschide numai în scriere (creare);
(sau O_CREAT)
- O_RDWR - fişierul se deschide în citire/scriere;
- O_APPEND - fişierul se deschide la sfârşit pentru adăugare;
- O_BINARY - fişierul se prelucrează binar;
- O_TEXT - fişierul este de tip text.
Unele valori din cele de mai sus se pot combina cu ajutorul operatorului |. De exemplu O_RDWR | O_BINARY pentru deschiderea fişierului în scriere/citire binară.
Observaţii:
1o. Funcţia open întoarce descriptorul de fişier care este o valoare intreagă ce va identifica fişierul în toate celelalte operaţii care se vor realiza asupra lui. Dacă deschiderea unui fişier nu reuşeşte (de obicei unul din parametrii este eronat) atunci funcţia open returnează valoarea –1.
2o. Pentru a putea utiliza funcţia open trebuie incluse fişierele header io.h şi fcntl.h.
3o. Pentru a crea un fişier nou se va folosi funcţia creat în locul funcţiei open cu prototipul:
int creat (const char *cale, int mod);
unde:
- cale are aceeaşi semnificaţie ca şi la funcţia open;
- mod este un întreg care poate fi definit prin constantele simbolice de mai jos:
S_IREAD - se poate citi fişierul;
S_IWRITE - se poate scrie în fişier;
S_IEXEC - se poate executa programul conţinut în fişier.
Utilizarea funcţiei presupune includerea fişierelor io.h şi stat.h
4o. Implicit fişierul se consideră că este de tip text.
Exemple:
-
char nume_fisier[ ]=”fis1.dat”;
int df;
df = open (nume_fisier, O_RDONLY);
Prin apelul de mai sus se deschide în citire fişierul fis1.dat din directorul curent.
-
int df;
df = open (“c:\\borlandc\\help.txt”,O_APPEND);
Se deschide în adăugare fişierul help.txt din directorul borlandc de pe discul C.
10.2.2. Citirea dintr-un fişier (consultare)
Funcţia folosită pentru operaţia de citire dintr-un fişier în memorie se numeşte read şi are prototipul următor:
int read (int df, void *buf, unsigned lung);
unde:
- df este descriptorul de fişier a cărui valoare a fost definită la deschidere;
-
buf este pointerul spre zona de memorie în care se recepţionează înregistrarea care se citeşte;
-
lung este lungimea în octeţi a inregistrării citite.
Observaţii:
1o. La fiecare apel funcţia returnează înregistrarea curentă. La primul apel se citeşte prima înregistrare din fişier, la al doilea apel se citeşte a doua, etc. Ordinea înregistrărilor în fişier este cea definită la crearea fişierului.
2o. La un apel al funcţiei read se citesc cel mult lung octeţi înregistrarea având definită lungimea la scrierea în fişier. Funcţia reîntoarce numărul de octeţi citiţi, 0(zero) la sfârşit de fişier, sau –1 la eroare. De obicei se folosesc frecvent înregistrări de 512 octeţi sau chiar mai mari.
3o. Funcţia read poate fi folosită pentru a citi de la intrarea standard. În acest caz, descriptorul de fişier este 0 (stdin are 0, stdout are 1, stderr are 2 stdprn are 3 stdaux are 4). Programatorul nu trebuie să deschidă fişierele standard deoarece ele sunt deschise automat la lansarea în execuţie a programului.
4o. Utilizarea funcţiei read, presupune includerea fişierului io.h.
10.2.3. Scrierea într-un fişier (creare, actualizare, adăugare)
Pentru a scrie într-un fişier se foloseşte funcţia write. Se presupune că fişierul este deschis în prealabil prin funcţia creat sau open. Ea este asemănătoare cu funcţia read, doar că realizează transferul invers, adică din memorie în fişier şi are prototipul:
int write (int df, void *buf, unsigned lung);
Observaţii:
1o. Funcţia returnează numărul octeţilor scrişi în fişier. Acesta este egal cu lung şi defineşte lungimea înregistrării scrise în fişier. În cazul în care numărul returnat de funcţia write diferă de parametrul lung scrierea a fost eronată şi se reîntoarce valoarea –1.
2o. Utilizarea funcţiei write implică includerea fişierlui io.h.
10.2.4. Poziţionarea într-un fişier
Pentru a avea acces aleator la înregistrările unui fişier se foloseşte o funcţie de poziţionare în fişier pe anumite înregistrări dorite. Pe fişierele care au suporturi magnetice este posibilă poziţionarea cu ajutorul funcţiei lseek care are prototipul următor:
long lseek (int df, long deplasament, int origine)
unde:
-
df este descriptorul de fişier;
-
deplasament defineşte numărul de octeţi peste care se va deplasa capul de
scriere/citire al discului;
-
origine are una din valorile:
0 deplasamentul se consideră de la începutul fişierului;
1 deplasamentul se consideră din poziţia curentă a capului de
scriere/citire;
2 deplasamentul se consideră de la sfârşitul fişierului.
Observaţii:
1o. Funcţia returnează poziţia capului de citire/scriere faţă de începutul fişierului în număr de octeţi sau –1L la eroare.
2o. Funcţia nu realizează nici un transfer de informaţie ci doar poziţionează capul de citire/scriere în fişier. Deci pentru transfer e nevoie de funcţiile read sau write.
3o. Utilizarea funcţiei presupune includerea fişierului io.h.
4o. Apelul lseek (df, 0L, 0) permite o poziţionare la început de fişier,
iar apelul lseek (df, 0L, 2) permite o poziţionare la sfârşit de fişier.
10.2.5. Închiderea unui fişier
La sfârşitul prelucrării unui fişier acesta trebuie închis. Acest lucru se realizează automat dacă programul se termină prin apelul funcţiei exit. Programatorul poate închide un fişier folosind funcţia close. Se recomandă închiderea unui fişier de îndată ce s-a terminat prelucrarea lui. Aceasta din cauză că numărul fişierelor ce pot fi deschise simultan este limitat. Limita este dependentă de sistemul de operare şi ea variază, de obicei, în intervalul 15-25. De obicei numărul de buffere (zone tampon) asociate fişierelor se precizează în fişierul autoexec.bat. Menţionăm că fişierele standard din limbajul C nu se închid de programator.
Funcţia close are prototipul următor:
int close (int df);
unde
df este descriptorul fişierului care se închide.
Observaţii:
1o. La o închidere normală, funcţia returnează valoarea 0 şi –1 în caz de incident.
2o. Utilizarea funcţiei close implică includerea fişierului io.h.
Exemple
-
Vom deschide fişierul “fis1.dat” în creare şi vom scrie în el două înregistrări.
#include
#include
void main (void)
{ int df,i;
df = open("fis1.dat", O_CREAT); // se deschide fisierul fis1.dat in creare
if (df != -1) // se testeaza daca fiserul s-a deschis corect
{ write (df,"cioban vasyle\n", 14); // se scriu doua inregistrari
write (df,"cioban andrei\n", 14);
} else printf (“nu s-a deschis fisierul);
close (df); // se inchide fisierul
}
-
Se afişează conţinutul fişierului “fis1.dat”
#include
#include
#include
#include
void main (void)
{int df;
char s[14];
df = open("fis1.dat", O_RDONLY); // se deschide fisierul în citire
if (df != -1) // se testeaza daca deschiderea e corecta
{ read (df, s, 14);
printf ("%.14s",s);
read (df, s, 14);
printf ("%.14s",s);
} else printf (“nu s-a deschis fisierul);
close (df);
getch(); // se asteapta un caracter de la tastatura
}
-
programul următor copiază intrarea standard la ieşierea standard folosind o zonă tampon de 80 de caractere:
#define LZT 80
#include
void main (void) // copiaza intrarea standard la iesirea standard
{ char zona_tampon[LZT];
int i;
while ((i = read (0, zona_tampon, LZT)) > 0) write (1, zt, i);
}
Dostları ilə paylaş: |