Fișiere

Pentru lucrul cu fișiere, există în C++ trei clase, ifstream (pentru citire), ofstream (pentru scriere), respectiv fstream (pentru operații mixte). Ambele sunt derivate din iostream, prin urmare operatorii și metodele sunt moștenite de la acestă clasă. Pentru a putea lucra cu clasele menționate trebuie inclusă biblioteca *ifstream.h*. Sintaxele pentru constructorii acestor clase sunt:

```
fstream id_fiser(cale/nume_fisier, ios::mod);

```

```
ifstream id_fiser(cale/nume_fisier);

```

```
ofstream id_fiser(cale/nume_fisier, [ios::mod]);

```

Constructorul *fstream* permite accesul la fișierul declarat, in mod mixt. Al doilea parametru al său stabileste modul de deschidere a fișierului. Valorile parametrului mod pot fi:

* in (fisierul este utilizat pentru citire)
* out (fisierul este utilizat pentru scriere; daca acesta exista, continutul este suprascris)
* append sau app (fișerul este deschis pentru adăugare)
* atend sau ate(pozitionează pointer-ul la sfârșitul fișierului, însă informațiile pot fi scrise oriunde în cadrul fișierului)
* truncate sau trunc (este modul de deschide implicit, în care vechiul conținut al fișierului este pierdut)
* nocreate (daca fisierul nu exista, atunci operatia esueaza)
* noreplace (dacă fișierul deja există, atunci operația eșuează)
* ios::binary (deschide fişierul în mod binar (implicit este text))

Constructorul *ifstream* permite implicit asocierea unui fișier în vederea preluării de date. *Id\_fisier* reprezinta numele logic pe care il va avea fisierul în program. *Cale* reprezinta calea catre folderul in care se găsește fișierul  specificat ulterior.

Alternativ, poate fi utilizată metoda open(), cu sintaxa:

```
open(cale/nume_fisier, mod, acces);

```

În acest caz, modul de deschidere a fișierului este determinat de enumeratorii: in (fişierul se deschide pentru citire; fişierul trebuie să existe), out  (fişierul se deschide pentru scriere; dacă există se şterge şi se crează un nou fişier), ate (fişierul se deschide pentru adăugare la sfârşit, dacă nu există se crează), app  (fişierul se deschide pentru adăugare la sfârşit; fişierul trebuie să existe), trunc (dacă fişierul există, va fi şters şi se va crea un fişier nou pentru scriere), nocreate (fişierul deschis trebuie să existe, neputând fi creat), noreplace ( fişierul este deschis, iar conţinutul lui nu poate fi înlocuit),  binary (fişerul deschis va fi prelucrat ca un fişier binar).  Modul de acces este determinat  de valorile: 0 (fişier fără restricţii de acces), 1 (fişier protejat la scriere), 2 (fişier ascuns), 4 (fişier sistem), 8 (fişier arhivă).

Iată, în continuare, două exemple de folosire a metodei open:

```
fstream f, g;

f.open("date.in", ios::in);

g.open("date.out",ios::out);

```

Închidere accesului la fișier, prin desfacerea legăturii fişier – stream, este asigurat de metoda close(), sintaxa ei fiind: id\_fisier.close();

În exemplul următor vom accesa fișierul date.in pentru a prelua textul din acesta, urmând să  scriem în fișierul date.out doar valorile alfabetice.

```
#include <iostream>

#include <fstream>

#include<string.h>

using namespace std;

int main()

{

ifstream f("date.in");

ofstream g("date.out");

char s[100];

int i;

while(f>>s)

{

  for(i=0;i<=strlen(s);i++)

       if((s[i]>='a'&&s[i]<='z')||((s[i]>='A'&&s[i]<='Z'))) g<<s[i];

  g<<'\n';

}

f.close();

g.close();

return 0;

}

```

Remarcăm că am putut utiliza operatorii de inserţie (<<) şi de extracţie (>>) , care sunt supraîncărcaţi, putând fi folosiţi pentru a scrie, respectiv citi din fişier. Ar mai trebui precizat că instrucțiunea while are ca expresie condițională expresia f>>s, cu o dublă semnificație: în primul rând extrage în șirul s un text din fișier (spațiile sunt considerate separatori), în al doilea rând, expresia este înlocuită cu un flux, extras din fișier. Astfel, când pointerul ajunge la capătul fișierului, s va conține NULL, iar programul oprește iterarea instrucțiunii while.

Pentru verificarea rezultatului operațiilor de intrare/ieșire, există următoarele metode:  eof() (pentru a verifica dacă s-a ajuns la sfârșitul fișierului), bad() (verifică dacă s-a executat o operatie invalidă), fail() (verifică dacă ultima operație a eșuat), respectiv good() (verifică dacă toate cele trei rezultate precedente sunt false).

Metoda get() poate fi folosită și în cazul fișierelor. Funcția poate prelua un singur caracter din fluxul de intrare sau poate prelua un număr maxim, precizat, ori până la întâlnirea unui anumit caracter. La întâlnirea EOF, funcția returnează NULL. Sintaxa funcției poate fi, în funcție de cele două posibile utuilizări:

```
id_fisier.get(caracter);

if_fisier.get(sir_caractere, număr, caracter_final);

```

Rescriem, în continuare, exemplul de mai sus, folosind, explicit metodele open(), eof(), respectiv get(), pentru realizarea diferitelor operații asupra fișierelor.

```
#include <iostream>

#include <fstream>

#include<string.h>

using namespace std;

int main()

{

fstream f,g;

f.open("date.in", ios::in);

g.open("date.out",ios::out);

int i;

char s[100];

while(!f.eof())

{      f.get(s, 100, EOF);

      for(i=0;i<strlen(s);i++)

           if((s[i]>='a'&&s[i]<='z')||((s[i]>='A'&&s[i]<='Z'))) g<<s[i];

g<<'\n';

}

f.close();

g.close();

return 0;

}

```

O altă metodă, utilizată în cazul intrării standard, pentru preluarea șirurilor de caractere, este getline(). Comportamentul său este asemănător cu al metodei get, diferența constând în aceea că getline nu preia și separatorul. Sintaxa metodei este:

```
id_fisier.getline(sir,numar, caracter) ;

```

Alături de metodele menționate, clasa fstream mai moștenește o serie de metode, care pot fi folosite în realizarea diferitelor sarcini.

Metoda peek() preia următorul caracter din flux, fără a-l extrage, returnând codul ASCII corespunzător. Sintaxa metodei este:

```
id_fisier.seek();

```

Metoda read() preia din fișier, într-un șir de caractere, un număr precizat de caractere. Sintaxa este:

```
id_fisier.read(sir_caractere, numar);

```

Metoda gcount() determină câte caractere s-au citit în ultima operaţie de citire. Sintaxa metodei este:

```
id_fisier.gcount();

```

Foarte utilă, în numeroase situații este metoda seekg(), al cărei rol este de a poziționa pointerul de fișier, cu un anumit număr de octeți în raport cu o poziție specificată ca parametru. Sintaxa metodei este: seekg(numar, pozitie). Număr reprezintă numărul de octeți va care se va face deplasarea. Parametru pozitie este indicat prin construcția ios::pos, unde pos poate avea una din valorile: beg(pentru pozitionare la început), cur(pentru poziționare în funcție de poziția actuală), respectiv end (poziționare se face în funcție de capătul fișierului).  De notat că funcția adminte pentru a preciza numărul de octeți și valori negative.

O altă metodă, utilă pentru a determina poziția curentă, este tellg(). Sintaxa este: id\_fisier.tellg(); Rezultatul returnat de această funcție este de tip long, reprezentând poziția la care se găsește pointerul de fișier.

Iată, mai jos, un exemplu de utilizare a funcțiilor seekg și tellg, în care se determină dimeniunea unui fișier text, urmând ca, apoi, să se extragă conținutul acestuia într-un șir de caractere, declarat de lungimea fișierului.

```
fstream f;

f.open("date.in", ios::in);

int lungime;

if (f)

   {

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

   lungime = f.tellg();

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

   char * sir = new char [lungime];

   f.read (sir,lungime);

   f.close();

   cout.write (sir,lungime);

   delete[] sir;

   }

```

Pentru operațiile de scriere în fișiere, pot fi utile următoarele metode: put(), respectiv, write().

Metoda put() scrie în fluxul de ieșire un caracter. Sintaxa ei este:

```
id_fisier.put(caracter);

```

Metoda write()  permite scriere în flux a unui șir de caractere. Sintaxa ei este:

```
id_fisier.write(sir_caractere, numar_caractere);

```