Lucrarea de laborator nr. 10

 

 

 

PRELUCRAREA FIŞIERELOR

DE CĂTRE NIVELUL INFERIOR AL  S.G.F.

 

 

 

1. Conţinutul lucrării

 

În lucrare sunt prezentate funcţiile de prelucrare a fişierelor la nivelul inferior, adică acelea care fac apel la sistemul de operare. Exemplul prezentat în lucrare ilustrează principalele operaţii asupra unui fişier: crearea, adăugarea, modificarea şi citirea unui fişier.

 

 

2. Consideraţii teoretice

 

Fişierul este o colecţie ordonată de înregistrări, memorate pe un suport extern.

Principalele operaţii asupra unui fişier sunt:

- deschiderea unui fişier existent;

- crearea unui fişier;

- citirea/scrierea într-un fişier;

- poziţionarea într-un fişier;

- ştergerea unui fişier.

 

             Prelucrarea unui fişier se poate face în două moduri:

a) utilizând funcţiile sistemului de operare (nivelul inferior);

b) utilizând funcţiile specializate de gestiune a fişierelor (nivelul superior).

 

              Modul de exploatare a unui fişier poate fi:

- secvenţial;

- direct.

 

               În lucrare sunt prezentate funcţiile de nivel inferior de prelucrare a fişierelor.

 

 

   2.1. Crearea unui fişier nou

 

   Pentru a avea un fişier nou, se utilizează funcţia creat, care are următorul prototip:

 

int creat (const char *calea_nume, int mod);

 

unde:

- calea_nume    - este un pointer spre un şir de caractere care defineşte calea de nume (path_name) a fişierului care se creează;

- mod               - este un întreg care poate fi definit prin combinarea cu "sau pe biţi" a următoarelor drepturi de acces:

            S_IREAD        - dreptul de citire;

            S_IWRITE       - dreptul de scriere.

 

                Funcţia returnează descriptorul de fişier în caz de succes sau -1 în caz de eroare.

                Funcţia creat necesită includerile de fişiere:

            #include <io.h>

            #include <sys/stat.h>

 

Observaţie importantă: deschiderea în creare a unui fişier existent conduce la ştergerea sa!

 

                Fişierul creat este exploatat în mod text (O_TEXT) sau binar (O_BINARY), după valoarea variabilei globale _fmode (implicit are valoarea O_TEXT).

 

                Exemplu:

 

            _fmode=O_BINARY;

            df=creat ("a:\\FIS.BIN”,S_IWRITE);

 

 

 

2.2. Deschiderea unui fişier existent

 

            Deschiderea unui fişier existent se face cu ajutorul funcţiei open, care are următorul prototip:

 

            int open (const char *calea_nume, int acces);

 

unde:

calea_nume - este un pointer spre un şir de caractere care defineşte calea de nume a fişierului existent;

acces - este un întreg care este generat prin combinarea pe biţi cu ajutorul operatorului "sau pe biţi " între următoarele constante:

O_RDONLY   - deschiderea pentru READ;

O_WRONLY  - deschiderea pentru WRITE;

O_RDWR        - deschiderea pentru READ şi WRITE;

O_APPEND    - pointerul în fişier va fi fixat pe sfârşitul de fişier înaintea fiecărei scrieri;

O_TRUNC      - dacă fişierul există, el este trunchiat la zero. Drepturile de acces la fişier rămân neschimbate;

O_BINARY    - modul de lucru binar;

O_TEXT          - modul de lucru caracter (implicit).

 

 

Observaţie: cu ajutorul funcţiei open, fişierul poate fi creat, caz în care open are prototipul următor:

 

int open (const char *cale_nume, int acces, unsigned mod);

 

În acest caz, accesul este o combinaţie între opţiunile prezentate anterior şi următoarele:

 

O_CREAT       - pentru crearea fişierului;

O_EXCL         - pentru a returna eroare în caz că fişierul există.

 

Opţiunile pentru parametrul mod sunt identice cu cele de la creat.

Fişierele care trebuie incluse sunt:

            #include <fcntl.h>

            #include <io.h>

Funcţia open returnează descriptorul de fişier sau -1 în caz de eroare.

 

Exemplu:

            df=open("C:\\limbaj_c\\FIS.DAT", O_RDWR);

 

Observaţie: numărul fişierelor deschise la un moment dat este limitat de obicei la 20.

 

2.3. Citirea dintr-un fişier

 

Citirea dintr-un fişier existent deschis cu open se face cu ajutorul funcţiei read, care are următorul prototip:

 

int read (int df, void *buf, unsigned lungime);

 

unde:

df                     - este descriptorul de fişier returnat de open la deschiderea fişierului respectiv;

buf                   - este pointerul spre zona de memorie în care se păstrează înregistrarea citită din fişier;

lungime - este lungimea în octeţi a înregistrării citite.

 

               Fişierul este interpretat ca o succesiune de octeţi, începând cu zero. După fiecare citire, indicatorul din fişier indică octetul cu care începe citirea următoare.

 

 

 

 

 


 

    

 

 

 

 

 

 

    La deschidere cu O_RDONLY sau O_RDWR, indicatorul este poziţionat pe octetul  0.

    Funcţia read returnează în caz de succes numărul de octeţi efectiv citiţi, iar în caz de eroare returnează -1, felul erorii fiind dat de variabila externă errno. În caz de întâlnire a sfârşitului de fişier (CTRL/Z), funcţia read returnează valoarea zero.

Fişierul standard de intrare are descriptorul de fişier zero.

Funcţia read necesită includerea fişierului io.h.

 

Exemplu. Citirea a 20 de octeţi din fişierul FIS.DAT aflat in directorul curent:

 

            df=open ("FIS.DAT", O_RDONLY);

n=read (df, adr, 20);

 

 

2.4. Scrierea într-un fişier

 

Scrierea într-un fişier deschis cu open sau cu creat se face cu ajutorul funcţiei write, care are ca prototip:

 

int write (int df, void *buf, unsigned lungime);

 

unde:

df                     - este descriptorul de fişier returnat de funcţia open sau creat;

buf                   - este pointerul spre zona de memorie din care se preia înregistrarea care se scrie în fişier;

lungime - este numărul de octeţi de scris.

 

            Funcţia returnează numărul de octeţi efectiv scrişi sau -1 în caz de eroare.

            Funcţia write implică includerea fişierului io.h.

            Funcţia write poate fi folosită pentru scrierea în fişierul standard, care are df=1;

 

             Exemplu: Scrierea în fişierul FIS.DAT din directorul curent  a 20 de octeţi  de la adresa adr:

 

df=creat ("FIS.DAT", S_IWRITE);

n=write (df,adr,20);

 

 

 

2.5. Poziţionarea într-un fişier

 

În cazul în care se doreşte citirea sau scrierea de la o anumită poziţie dintr-un fişier pe suport magnetic, se utilizează funcţia lseek, care are prototipul:

 

long lseek (int df, long increment, int origine);

 

unde:

df                     - este descriptorul de fişier deschis;

increment          - numărul de octeţi peste care se va poziţiona indicatorul în fişier, ţinând cont de parametrul origine;

origine              - are una din valorile:

            0 - incrementul se consideră faţă de începutul fişierului;

            1 - incrementul se consideră faţă de poziţia curentă a indicatorului de fişier;

            2 - incrementul se consideră faţă de sfârşitul fişierului.

 

Funcţia returnează deplasamentul rezultat faţă de începutul fişierului sau -1 în caz de eroare. Utilizarea funcţiei necesită includerea fişierului io.h.

 

Exemple:

 

a) poziţionarea indicatorului la începutul fişierului:

lseek(df,0l,0);

b) poziţionarea indicatorului la sfârşitul fişierului, caz utilizat pentru adăugarea de noi înregistrări în fişier :

lseek (df, 0l, 2)

 

2.6. Închiderea unui fişier

 

După terminarea prelucrării unui fişier, acesta se închide apelând funcţia close, care are prototipul:

int close(int df);

 

df fiind descriptorul fişierului.

Funcţia returnează zero în caz de succes sau  -1 în caz de eroare.

Folosirea funcţiei necesită includerea fişierului io.h.

 

2.7. Exemplu

 

În programul următor sunt ilustrate următoarele operaţii asupra unui fişier:

- crearea fişierului;

- adăugarea de noi înregistrări;

- modificarea unor înregistrări. În acest caz se poziţionează indicatorul în fişier pe începutul înregistrării şi se scrie noua înregistrare;

- citirea şi afişarea conţinutului fişierului;

- sortarea fişierului, având drept cheie media, un câmp din înregistrare. Întrucât numărul înregistrărilor unui fişier este mare, s-au citit iniţial înregistrările din care s-au extras cheile de sortare, reţinându-se numărul de ordine al înregistrărilor şi se ordonează în memoria interna. Apoi se obţine fişierul sortat.

 

 

 /* Programul L10Ex1.cpp */

 

 #include <stdio.h>

 #include <conio.h>

 #include <io.h>

 #include <fcntl.h>

 #include <sys\stat.h>

 #include <process.h>

 #include <stdlib.h>

 /* Exemplu de utilizare a fişierelor */

 typedef struct{

                                     char nume[32];

                                     float media;

                                     /*alte informaţii */

                        } STUDENT;

 typedef union {

                                     STUDENT stud;

                                     char st[sizeof(STUDENT)];

                        } BUF;

 typedef struct {

                                    int nr;

                                    float med;

                         } ELEMENT;

 

 void sortare(char nume_fis[],char nume_fis_sortat[])

  {

                         ELEMENT el,t[100];

                         int k,j,n,i,df1,df2;

                         BUF stu;

                         j=0;

                         df1=open(nume_fis,O_RDONLY);

                         while (read(df1,stu.st,sizeof(STUDENT))>0)

                                     {

                                      t[j].nr=j;

                                      t[j].med=stu.stud.media;

                                      j=j+1;

                                     };

                         /* Sortarea tabloului t după medie */

                                    n=j-1;/* Elementele tabloului t sunt 0,1,2,...,n */

                                    j=0;

                                    do

                                                {

                                                  k=1;j=j+1; /*k=TRUE*/

                                                  for(i=0;i<=n-j;i++)

                                                             if (t[i].med > t[i+1].med)

                                                             {

                                                                        el=t[i];t[i]=t[i+1];t[i+1]=el;

                                                                         k=0;/*k=FALSE */

                                                              };

                                                 }

                                      while(k==0);

                          close(df1);

                         /*Crearea fişierului sortat */

                         df2=creat(nume_fis_sortat,S_IWRITE|S_IREAD);

                         df1=open(nume_fis,O_RDONLY);

                         for(i=0;i<=n;i++)

                                    {

                                      lseek(df1,(long)(t[i].nr * sizeof(STUDENT)),0);

                                      read(df1,stu.st,sizeof(STUDENT));

                                      write(df2,stu.st,sizeof(STUDENT));

                                     };

                          close(df1);

                          close(df2);

            }

 

 void afisare( char nume_fis[])

 {

            BUF stu;

            int j,df1;

            j=0;

            df1=open(nume_fis,O_RDONLY);

            while (read(df1,stu.st,sizeof(STUDENT))>0)

              {

                  printf("\n%d  %-32s %7.2f", j, stu.stud.nume,

                                  stu.stud.media);

                  j=j+1;

              };

            close(df1);

 }

 

 

 void main()

 {

  int i,n,m,df1;long l;

  char ch;

  BUF stu;

  char nume_fis[50]="c:\\ignat\\Limbaj_C\\grupa.dat";

  char nume_fis_sortat[50]="c:\\ignat\\Limbaj_C\\grupasort.dat";

  printf("\nNr.studentilor de introdus n=");

  scanf("%d",&n);

  /*crearea fişierului */

  if ((df1=creat(nume_fis,S_IWRITE|S_IREAD))==-1)

            {

              printf("Nu se poate crea fişierul\n");

              exit(1);

            }

  /* Introducerea datelor despre studenti */

  for(i=1;i<=n;i++)

             {

                        printf("\nNumele studentului: ");

                        scanf("%*c");

                        gets(stu.stud.nume);

                        printf("\nMedia=");

                        scanf("%f",&stu.stud.media);

                        write(df1,stu.st,sizeof(STUDENT));

             };

  close(df1);  /* Închiderea fişierului */

 

  /*Adăugarea de noi articole in fişier */

  printf("\nNr.studentilor de adaugat m=");

  scanf("%d",&m);

  df1=open(nume_fis,O_RDWR);

  lseek(df1,0l,2);

  for(i=1;i<=m;i++)

             {

                        printf("\nNumele studentului adăugat: ");

                        scanf("%*c");

                        gets(stu.stud.nume);

                        printf("\nMedia=");

                        scanf("%f",&stu.stud.media);

                        write(df1,stu.st,sizeof(STUDENT));

             };

  close(df1);  /*Închiderea fişierului */

  printf("\n FIŞIERUL DUPA CREARE\n");

  afisare(nume_fis);

            /* Modificarea datelor din fişier */

   printf("\n Modificati? DA=D/d NU= alt caracter ");

   scanf("%*c%c",&ch);

   df1=open(nume_fis,O_RDWR);

            while((ch=='D')||(ch=='d'))

              {

                        printf("Nr.de ordine al studentului =");

                        scanf("%d%*c",&i);

                        l=lseek(df1,(long)(sizeof(STUDENT) *i),0);

                        printf("depl=%ld pentru i=%d\n",l,i);

                        read(df1,stu.st,sizeof(STUDENT));

                        printf("\nNumele vechi este:%s\n",stu.stud.nume);

                        printf("\nNumele modificat:");

                        gets(stu.stud.nume);

                        printf("\n Media veche este: %f",stu.stud.media);

                            printf("\nMedia modificată=");

                        scanf("%f",&stu.stud.media);

                        l=lseek(df1,(long)(sizeof(STUDENT) *i),0);

                        printf("depl=%ld pentru i=%d\n",l,i);

                        write(df1,stu.st,sizeof(STUDENT));

                        printf("\n Mai modificati? DA=D/d NU=alt caracter  ");

                        scanf("%*c%c",&ch);

              }

             close(df1);

             printf("\nCONŢINUTUL FISIERULUI NESORTAT\n");

             afisare(nume_fis);

             getch();

             printf("\nCONŢINUTUL FISIERULUI SORTAT\n");

             sortare(nume_fis,nume_fis_sortat);

             afisare(nume_fis_sortat);

             getch();

 }

 

3. Mersul lucrarii

 

3.1. Se va executa şi analiza programul L10Ex1.cpp

 

3.2. Se citeşte de la tastatură un text care se scrie într-un fişier "text.dat". Să se afişeze apoi conţinutul fişierului, fiecare linie fiind precedată de numărul de ordine al ei.

 

3.3. De la tastatură se citesc partea reală şi partea imaginară pentru n numere complexe. Să se creeze un fişier care conţine numerele complexe citite, fiecare număr având partea reală, partea imaginară, modulul şi argumentul său.

 

3.4. Două firme îşi păstrează informaţiile referitoare la stocul de mărfuri (cod produs, denumire, cantitate, preţ unitar) în fişierele "marfa1.dat" şi respectiv "marfa2.dat", ordonate crescător după cod. Prin fuzionarea celor două firme, rezultă un stoc comun care trebuie memorat în fişierul "marfa.dat", ordonat după cod.

                    a) Să se creeze fişierele iniţiale, pe baza datelor introduse de la tastatură şi apoi să se creeze fişierul de stoc comun "marfa.dat" Pentru mărfuri cu cod comun, se consideră că denumirea şi preţul unitar corespund.

                   b) Fişierul "marfa.dat" se va parcurge secvenţial, tipărind pentru fiecare componentă denumirea şi cantitatea.

                   c)Pentru o componentă dorită dată prin numărul de ordine, se va modifica direct preţul său unitar.

 

3.5. Să se scrie programul pentru concatenarea a două sau mai multe fişiere ce conţin numere reale. Se va tipări informaţia din fişierul rezultat.