Informatica
Doriți să reacționați la acest mesaj? Creați un cont în câteva clickuri sau conectați-vă pentru a continua.

Operatii de intrare/iesire cu fisiere in c++

Informatica :: IT :: C++

In jos

Operatii de intrare/iesire cu fisiere in c++    Empty Operatii de intrare/iesire cu fisiere in c++

Mesaj  Admin Sam Mar 03, 2012 11:29 am

• Modelul fundamental pentru constructia bibliotecii IOSTREAM este cel de stream, vazut ca un flux de date de la o anumita sursa la o anumita destinatie. Aceasta biblioteca consta din mai multe clase, organizate in doua ierarhii paralele.

a) O ierarhie de clase streambuf, care realizeaza gestionarea bufferelor utilizate de fluxuri, in efectuarea operatiilor de intrare/iesire. Obiecte ale clasei filebuf, care este o clasa derivata a clasei streambuf, sunt folosite la prelucrarea fisierelor. Aceste obiecte sunt folosite de clase specifice pentru operatii cu fisiere, care sunt cuprinse in ierarhia care porneste de la clasa de baza ios.

b) O ierarhie de clase ios, care gestioneaza toate operatiile de intrare/iesire, si pune la dispozitie o interfata la nivel inalt pentru programator. Aceasta ierarhie foloseste mostenirea multipla in obtinerea clasei derivate iostream, pentru ca ea mosteneste atat clasa istream, pentru realizarea operatiilor de intrare, cat si clasa ostream, pentru realizarea operatiilor de iesire. #n aceasta ierarhie, sunt definite clasele derivate fstreambase, istream si ostream, avand clasa de baza ios.

• Avand in vedere faptul, ca cele mai uzuale fisiere sunt cele de pe disc, ne vom ocupa de operatii de prelucrare a fisierelor inregistrate pe discuri.

• Pentru a efectua operatii de intrare/iesire cu fisiere, trebuie inclus in program fisierul antet FSTREAM.H. In acest fisier sunt definite:
1) clasa ifstream, pentru operatii de intrare (citire), care este o clasa derivata de la clasele fstreambase si istream;
2) clasa ofstream, pentru operatii de iesire (scriere), care este o clasa derivata de la clasele fstreambase si ostream;
3) clasa fstream, pentru operatii de intrare/iesire (citire/scriere), care este o clasa derivata de la clasele fstreambase si iostream;

• In ierarhia de clase ios, se afla definite si clasele:
1) istream_withassign, derivata de la clasa istream;
2) ostream_withassign, derivata de la clasa ostream;
3) iostream_withassign, derivata de la clasa iostream;
In constructia acestor clase derivate se adauga definitia operatorului de atribuire (=) si sunt utile in redirectionarea operatiilor de intrare/iesire prin atribuirea unui flux, unui alt flux.

• Prelucrarea unui fisier de pe disc incepe cu operatia de deschidere a sa. Deschiderea unui fisier se poate realiza:
a) folosind functia membra open ca un obiect al uneia din clasele ifstream, ofstream sau fstream instantiat fara parametri.
b) crearea unei instante a clasei ifstream (pentru citire), ofstream (pentru scriere), sau fstream (pentru citire/scriere);

• #n situatia a), dupa ce s-a creat streamul, el este asociat unui fisier cu ajutorul functiei open( ).
void open(const char*id_fisier, int mod, int acces=filebuf::openprot);
unde:
- id_fisier este numele fisierului care poate include si calea de acces;
- mod precizeaza modul de deschidere al fisierului. El poate fi:
ios::app
// valoare utila fisierului ce accepta iesiri. Se adauga inregistrari la sfarsitul fisierului.
ios::ate
// la deschiderea pentru prima data a fisierului, pozitionare la sfarsitul sau. Operatiile de // intrare/iesire pot avea loc oriunde in interiorul fisierului.
ios::binary
// deschiderea unui fisier cu scopul de a fi prelucrat in binar (nu se accepta modificari de // caractere). #n mod implicit fisierele se deschid in mod text (prelucrare pe caractere).
ios::in
// deschide fisier pentru citire (fisierul accepta intrari).
ios::out
// deschide fisier pentru scriere (fisierul accepta iesiri).
ios::nocreate
// deschiderea unui fisier existent (nu se deschide fisier in creare).
ios::noreplace
// nu se poate deschide un fisier existent pentru iesire, cu exceptia situatiei in care sunt
// operate ios::ate sau ios::app.
ios::trunc
// daca exista un fisier cu numele specificat este distrus si se creeaza un fisier nou.

• Crearea unui stream folosind ifstream implica intrari si nu mai este necesara introducerea valorii ios::in. Crearea unui stream folosind ofstream implica iesiri si nu mai este necesara introducerea valorii ios::out.

• Majoritatea implementarilor indica tipul parametrului mod ca fiind int. Se pot combina doua sau mai multe valori ale lui mod, folosind operatorul logic OR ( | ).

- parametrul acces are valoarea implicita filebuf::openprot, care indica acces la un fisier normal. In mod implicit, valoarea acestui parametru de protectie este 0.

Exemple:
// deschideri de fisiere
1.
ifstream fis;
fis.open(“f.dat”, ios::nocreate);
// se deschide fisierul existent “f.dat”, pentru citire. Optiunea ios::in este implicita.
if(!fis)
{
cerr<<”Deschidere eronata ! \n”;
exit(1);
}
else {....}

2.
ofstream fis;
fis.open(“fisa.dat”);
// deschiderea unui fisier normal de iesire. Optiunea ios::out este implicita.
if(!fis)
{
cerr<<”Deschidere eronata ! \n”;
exit(1);
}
else {....}
3.
ofstream fis;
fis.open(“pers.dat”, ios::app | ios::binary);
// se deschide fisierul binar “pers.dat”, pentru adaugare de inregistrari la sfarsit.
if(!fis)
{
cerr<<”Deschidere eronata ! \n”;
exit(1);
}
else {....}

• In situatia b) , instantierea obiectelor claselor ifstream, ofstream, fstream, produc apelul constructorilor necesari instantierilor, care apeleaza in mod automat, functia de deschidere open( ). Acesti constructori au aceiasi parametri ca si functia de deschidere. Se procedeaza astfel:
1) # include <fstream.h>
2) se definesc clasele ifstream/ofstream;
3) se deschide fisierul cu numele “id_in_fis” / “id_out_fis” pentru operatii de intrare / iesire;
4) conectez fisierul la instanta ifstream “inf”/ ofstream “outf”;
ifstream inf(“id_in_fis”);
ofstream outf(“id_out_fis”);
5) se verifica corectitudinea operatiei de creare a fluxului, prin supraincarcarea operatorului logic de negare (!) pentru clasele de fluxuri;
if(!inf)
{
cerr<<”Eroare in operatia de deschidere a fisierului !\n”;
exit(1);
}

• Asadar, se poate deschide un fisier si conecta la un flux, in momentul crearii fluxului. Conectarea unui fisier la o instanta ifstream (flux pentru intrare), este echivalent in ANSI C, cu apelul functiei fopen cu modul r. Conectarea unui fisier la o instanta ofstream (flux pentru iesire), este echivalent in ANSI C, cu apelul functiei fopen cu modul w.
Exemple:
// deschideri de fisiere. Se rescriu, in aceasta ipoteza, exemplele anterioare.

1.
ifstream fis (“f.dat”, ios::nocreate);
if(!fis)
{
cerr<<”Deschidere eronata ! \n”;
exit(1);
}
else {....}

2.
ofstream fis(“fisa.dat”);
if(!fis)
{
cerr<<”Deschidere eronata ! \n”;
exit(1);
}
else {....}
3.
ofstream fis(“pers.dat”, ios::app | ios::binary);
if(!fis)
{
cerr<<”Deschidere eronata ! \n”;
exit(1);
}
else {....}

• Dupa incheierea procesului de prelucrare a fisierului, care a fost deschis, el trebuie inchis. Inchiderea unui fisier se realizeaza cu ajutorul functiei membra close( ).
obiect.close( );
sau
ptr_obiect->close( );
unde obiect este o instantiere a uneia din clasele ifstream, ofstream sau fstream, iar ptr_obiect este un pointer spre unul din tipurile implementate prin aceste clase.
Exemplu:
fis.close( ); // functia close( ) nu are parametri si nu returneaza nici o valoare.

• In prelucrarea fisierelor tip text existente pe disc, se pot folosi functiile membre ale claselor istream, ostream si iostream, pentru ca ele sunt clase de baza pentru clasele specifice prelucrarii fisierelor pe disc. Ca atare, se pot folosi operatorii de inserare/extragere (<< , >>), pentru operatii de scriere/citire cu format, intr-un/ dintr-un fisier de pe disc. Se vor inlocui cin si cout cu un stream conectat cu fisierul respectiv.
Exemplu:
// se creeaza un fisier de evidenta a unor persoane, care contine numele si varsta.
# include<iostream.h>
# include<fstream.h>
main( ){
ofstream fis_o(“FISA”);
if(! fis_o){
cout<<”Eroare la deschidere ! \n”;
return 1;
}
fis_o<<”Popescu”<<25<<”ani”<<endl;
fis_o<<”Georgescu”<<40<<”ani”<<endl;
fis_o<<”Marinescu”<<56<<”ani”<<endl;
fis_o.close( );
return 0;
}

// program prin care se citeste si se afiseaza continutul fisierului precedent.
# include<iostream.h>
# include<fstream.h>
main( ){
ifstream fis_i(“FISA”);
if (! fis_i){
cout<<”Eroare la deschiderea lui fis_i\n”;
return 1;
}
char numea25];
int varsta;
fis_i>>nume>>varsta;
cout<< nume<<”:”<<varsta<<”\n”;
fis_i>>nume>>varsta;
cout<< nume<<”:”<<varsta<<”\n”;
fis_i>>nume>>varsta;
cout<< nume<<”:”<<varsta<<”\n”;
fis_i.close( );
return 0;
}

• In prelucrarea fisierelor de tip binar, exista doua posibilitati de citire/scriere a datelor.
a) utilizarea functiilor membre de:
- intrare (citire)
istream &get(char &ch);
(citeste un caracter din streamul asociat si memoreaza valoarea in ch, apoi returneaza o referinta catre stream).
Functia get( ) poate fi supraincarcata sub una din formele urmatoare:
1) istream&get(char*bf, int nr, char dl=’\n’);
(citeste nr caractere dintr-un tablou bidimensional indicat de bf. In cazul in care se intalneste caracterul precizat prin dl (delimitator), functia va incheia cu null tabloul respectiv. Un astfel de caracter, in mod implicit, este caracterul de linie noua. Daca delimitatorul este intalnit in streamul de intrare, el nu este extras si ramane in stream pana la urmatoarea operatie de citire.)
2) int get( );
(returneaza urmatorul caracter din stream sau EOF daca se intalneste sfarsitul de fisier).
Spre deosebire de functia
istream&get(char*bf, int nr, char dl=’\n’);
functia
istream&getline(char*bf, int nr, char dl=’\n’);
in plus, citeste si extrage delimitatorul din streamul de intrare.

- iesire (scriere)
ostream &put(char ch);
( scrie ch in stream si returneaza o referinta catre stream).

b) utilizarea functiilor de citire/scriere, in C++, a unor blocuri de date in binar:
- intrare (citire)
istream&read(unsigned char*bf, int nr);
(citeste nr octeti din streamul asociat si ii plaseaza in bufferul indicat de bf. Daca se ajunge la sfarsitul fisierului dupa un numar nr_1<nr de octeti (caractere) cititi, operatia de citire se incheie, iar in buffer se vor gasi caracterele citite.).
Evidenta numerica a octetilor existenti in buffer se poate stabili cu ajutorul functiei membre:
int gcount( );

- iesire (scriere)
ostream&write(const unsigned char*bf, int nr);
(scrie in streamul asociat nr octeti pe care ii citeste din bufferul indicat de bf).
Exemplu:
//program utilitar de copiere a unui fisier sursa intr-un fisier destinatie
#include<fstream.h>
#include <iostream.h>
#include<string.h>

main(int argc, char*argv[]){
fstream infis,outfis;
if (argc>1){
// se specifica fisierul de intrare
infis.open(argv[1],ios::in|ios::binary);
if(!infis)
{
cerr<<"Eroare la deschiderea fis_intrare"<<argv[1]<<"\n";
return (1);
}
}
if(argc>2){
// se specifica fisierul de iesire
outfis.open(argv[2],ios::out);
if(!outfis)
{
cerr<<"Eroare la deschiderea fis_iesire"<<argv[2]<<"\n";
return (1);
}
}
const dimbuf=255;
char buf[dimbuf];
while(infis.get(buf,dimbuf,'\n')&&outfis)
outfis.write(buf,strlen(buf));
return 0;
}

Exemplu:
//utilizarea functiilor read( ) ]i write( )
# include<iostream.h>
# include<fstream.h>
# include<string.h>
typedef struct
{
int zi;
int luna;
int an;
}data_c;
main( ){
data_c dt;
dt.an=1999;
dt.luna=12;
dt.zi=25;
ofstream outfis("termen",ios::out|ios::binary);
if(!outfis)
{
cout<<"Eroare la deschidere.\n";
return (1);
}
outfis.write((unsigned char*)&dt, sizeof(data_c));
outfis.close();
ifstream infis("termen",ios::in|ios::binary);
if(!infis)
{
cerr<<"Eroare la deschderea fis infis\n";
return (1);
}
infis.read((unsigned char*)&dt, sizeof(data_c));
cout<<dt.an<<endl;
cout<<dt.luna<<endl;
cout<<dt.zi<<endl;
infis.close( );
return 0;
}

• Alte functii utile in prelucrarea unui fisier:
1) int eof( );
(returneaza valoarea 0, daca s-a intalnit sfarsitul de fisier, sau diferita de zero, in caz contrar).
2) istream&ignore(int nr(=1), int dl=EOF);
(citeste si elimina, din streamul de intrare, un numar de nr caractere sau pe cele intalnite pana la delimitatorul dl. Nu extrage delimitatorul din streamul de intrare.)
3) int peek( );
(returneaza urmatorul caracter din streamul de intrare sau EOF daca s-a intalnit sfarsitul de fisier)
4) istream&putback(char ch);
(returneaza, in acelesi stream, ultimul caracter citit ch)
5) ostream&flush( );
(solicita scrierea efectiva a datelor pe disc, inainte de umplerea bufferului)

• Specificarea pozitiei relative, intr-un fisier, in raport cu un anumit punct de referinta (acces aleator):

a) istream&seekg(streamoff offset, seek_dir orig);

b) ostream&seekp(streamoff offset, seek_dir orig);

unde streamoff este un tip definit in iostream.h, apt de a retine cea mai mare valoare valida a lui offset, iar seek_dir consta intr-o enumerare cu urmatoarele valori:
ios::beg // inceput de fisier
ios::cur //pozitia curenta
ios::end// sfarsit de fisier

Sistemul de intrare/iesire din C++ opereaza cu un pointer get, care precizeaza pozitia urmatoarei operatii de intrare in fisier, si un pointer put, care precizeaza pozitia urmatoarei operatii de iesire in fisier. Dupa fiecare operatie, pointerul respectiv avanseaza, in mod secvential.
Functiile mentionate permit un acces nesecvential la fisierul care urmeaza a fi prelucrat.
Functia seekg( ) deplaseaza pointerul get al fisierului asociat cu un numar de octeti dat de valoarea offset in raport cu originea mentionata prin orig.
Functia seekp( ) deplaseaza pointerul put al fisierului asociat cu un numar de octeti dat de valoarea offset in raport cu originea mentionata prin orig.

• Utilizarea functiilor anterioare sub forma

a) istream&seekg(streampos p);

c) ostream&seekp(streampos p);
permit salvarea pozitiei curente a fisierului, efectuand alte operatii pe fisier, si revenind la pozitia salvata anterior. Tipul definit in iostream.h, streampos, este apt de a retine cea mai mare valoare pe care o poate returna una din cele doua functii.

• Starea curenta a sistemului de intrare/iesire este retinuta intr-un intreg in care se afla codificati urmatorii indicatori ( enumerati in clasa ios):
a) eofbit // 1 pentru sfarsit de fisier si 0 in caz contrar
Functia
int eof( ); // returneaza o valoare nenula (adevarat) daca este activat eofbit
b) badbit // 1 cand apare o eroare fatala si 0 in caz contrar
Functia
int bad( ); // returneaza o valoare nenula (adevarat) daca este activat badbit
c) failbit // 1 cand apare o eroare de intrare/iesire si 0 in caz contrar
Functia
int fail( ): // returneaza o valoare nenula (adevarat) daca este activat failbit
d) goodbit // valoarea 0 (fara eroare)

Functia
int good( ); // returneaza adevarat daca nu exista erori si 0 in caz contrar.

• Starea curenta a sistemului de intrare/iesre se poate stabili prin apelarea functiilor mentionate anterior, sau prin functia:
int rdstate( );// returneaza 0 daca nu exista erori.

Aplicatie:
Sa se scrie un program care sa citeasca de la intrarea standard date cu urmatorul format:
cod_acces den_tren nr_tren viteza nr_vag.

Sa se scrie, prin programul respectiv, datele din directorul curent in fisierul “tren.dat”.

#include<iomanip.h>
#include<stdlib.h>
#include<fstream.h>
typedef struct
{
char cod_acces;
char den_tren[15];
int nr_tren;
int viteza;
int nr_vag;
}tren;
union{
tren p[3];
char pt[3*sizeof(tren)];
}tamp;
int citinf(tren*ptr)
{
char tab[255];
int v,nr;
for(;Wink
{
cout<<"cod_acces den_tren nr_tren viteza nr_vag";
if((cin>>setw(4)>>ptr->cod_acces)&&(cin>>setw(15)>>ptr->den_tren)&&
(cin>>setw(4)>>ptr->nr_tren)&&(cin>>v>>nr))
{
ptr->viteza=v;
ptr->nr_vag=nr;
return 1;
}
if(cin.eof( )) return 0; //EOF
cin.clear( ); // anuleaza eroarea
cin.getline(tab,255,'\n'); } }
main( ){
// se creeaza fisierul binar "tren.dat"
ofstream trafic("tren.dat",ios::binary);
int k;
if(!trafic){
cout<<"Eroare la deschiderea fisierului in creare\n";
exit(1);
}
for(; ; ){
for(int j=0;j<3;j++)
if((k=citinf(&tamp.p[j]))==0)break; //EOF
if(j){
// zona tampon este nevida
trafic.write(tamp.pt,j*sizeof(tren));
if(!trafic){
cout<<"Eroare la scriere in fisier";
exit(1);
}
}
if(k==0)break; // EOF
}
trafic.close( );
}

Sa se scrie un program care sa afiseze datele din fisierul creat “tren.dat”, conform “cod_acces” solicitat.

#include<iomanip.h>
#include<stdlib.h>
#include<fstream.h>
typedef struct
{
char cod_acces;
char den_tren[15];
int nr_tren;
int viteza;
int nr_vag;
}tren;
union{
tren p[3];
char pt[3*sizeof(tren)];
}tamp;

main( ){
// se creeaza fisierul binar "tren.dat"
ifstream trafic("tren.dat",ios::binary);
int k;
if(!trafic){
cout<<"Eroare la deschiderea fisierului in creare\n";
exit(1);
}
cout<<"\n\n"<<setw(19)<<"INSTANTA"<<"\n\n";
do{
trafic.read(tamp.pt,3*sizeof(tren));
k=trafic.gcount()/sizeof(tren);
for(int j=0;j<k;j++) {
if((tamp.p[j].cod_acces=='2')|(tamp.p[j].cod_acces=='0'))
{
cout<<"\n";
cout.setf(ios::right,ios::adjustfield);
cout<<setw(1)<<tamp.p[j].cod_acces;
cout.setf(ios::left,ios::adjustfield);
cout<<' '<<setw(15)<<tamp.p[j].den_tren;
cout.setf(ios::left,ios::adjustfield);
cout<<setw(4)<<tamp.p[j].nr_tren;
cout<<tamp.p[j].viteza;
cout<<' '<<setw(3)<<tamp.p[j].nr_vag;
}}
}while(trafic);
if(!trafic.eof( ))
cout<<"Citire eronata!\n";
trafic.close( );
}
Admin
Admin
Admin
Admin

Mesaje : 1113
Data de inscriere : 02/03/2012

http://dutu.p.ht/

Sus In jos

Sus

- Subiecte similare

Informatica :: IT :: C++

 
Permisiunile acestui forum:
Nu puteti raspunde la subiectele acestui forum