Sunteți pe pagina 1din 9

FISIERE BINARE - BOJA

Int credite[10] e un vector static si este bine sa nu ne bazam ca vom avea mereu fix 10
valori asa ca mai bine il destionam cu un int nrCredite (ca poate nu folosim toate cele 10 valori).
In constructor avem nevoie de int* (mai bine spunem ca trimitem un pointer la un vector.
De ce? Pentru ca pe anumite compilatoare , daca pui un int [10] si tu nu dai in main un vector de
10 risc sa am o eroare de compilare sau la executie.
Toti pointerii la vectorii statici sunt constanti.
Deci nu copiem vectorii cu egal!!
Pentru vectori statici nu alocam memorie ci doar o parcurgem cu for!!! La vectorii
dinamici alocam memorie.
La char static (char nume[50]) facem doar strcpy!! Si la char* alocam dinamic.
Ofstream e derivat din ostream.

//afisare fisier text


In loc de cout am ofstream (output file stream)
ofstream raport(“student.txt”,ios::app) //numele fisierului
//modul de deschidere pentru fisier binar, pt ca implicit e text!
//pt append e app, altfel este implicit trunc - suprascriere in fisier text
Daca fisierul nu exista, se creeaza, deci nu e obligatoriu sa-l verificam, e mult mai riscant
deschiderea in mod citire, acolo trebuie facuta aceasta verificare pt ca dcaa fisierul nu exista in
locatia respective nu are cum sa se deschida.
if (raport.is_open()) {
raport << s1;
raport << s2;
raport << s3;
//raport << s1 << s2 << s3;
raport.close(); //trebuie inchis dupa ce lucram cu el
}
else
{ cout << endl << "EROARE Fisierul nu a fost creat";
}
FISIERE BINARE - BOJA

La afisare (input stream) din fisier text avem cate o valoare pe linie si inainte de vector punem
numarul de elemente din vector!! Si fara comentarii!!
Nu avem spatii!! Daca vrem sa citeasca si spatii punem getline;

Fisiere binare

Serializare= se iau toate datele din memorie si se duc intr-o secventa continua de biti. E ca si
cum am liniariza ceva ce e imprastiat in heap.

//scriere
ofstream fisierDate(“studenti.dat”,ios::binary) //numele fisierului
//implicit toate fisierele scrise sunt text asa ca le schimbam in binar, pentru ca altfel descarcam
intr-un fisier text.
//implicit e trunc, nu vreau sa fac append
//daca fac append si voi tot apela acel fisier text va creste numarul de obiecte pentru ca se adauga
(append)
//aici lasam implicit trunc (putem si sa scriem dar oricum e implicit trunc)
if (fisierDate.is_open()) {
raport << s1;
raport << s2;
raport << s3;
//raport << s1 << s2 << s3;
fisierDate.write(s1);

fisierDate.close(); //trebuie inchis dupa ce lucram cu el


}
else
{ cout << endl << "EROARE Fisierul nu a fost creat";
}
//daca nu merge poate nu avem drepturi de scriere pe locatie sau nu avem suficient spatiu
FISIERE BINARE - BOJA

La fisierele binare nu se scrie cu << pt ca face conversia la text pentru toate valorile. Testul
prin care verificam daca scriem binar sau text, e sa punem << (e ca si cum am scrie in fisier binar
ceva ce e text).

Cum obtin adresa unei variabile? Folosim &.


Write vrea ca toti pointerii sa fie de tip char*.
&s1 este pointer la student.
fisierDate.write((char*)&s1,sizeof(Student)) //are 2 parametrii, adresa convertita la char* si nr
de baiti al variabilei pe care vreau sa o descarc.
Stringurile se vad intotdeauna in fisierele binare!!

Cand alocam noi spatiu apare in heap.

Sizeof() este foar bucata de Student, adica cat ocupa fiecare atribut si atat. Deci in fisierul binar
se scrie doar adresa care imi spune mie unde se gasesc notele. La campurile dinamice nu se scriu
adresele!
Varianta simpla nu merge pentru obiectele ce contin minim un camp dinamic!!

Serializarea e ca si cum am reconstrui noi intr-un fisier binar obiectul nostru bucatica cu
bucatica.

//metoda care scrie datele obiectului intr-un fisier binar


void scrieStudent(ofstream& fisierBinar) { //nu trebuie sa intoarca nimic
//trebuie sa stabilim o ordine de scriere (lista atributelor mai bine)
//aici nu folosim <<, pt stringuri ar merge dar nu e ok
//scriu id-ul INT (care este o valoare sau o adresa? Este o valoare, deci am nevoie de
adresa lui, pun & si fac cast la char*, si al 2-lea param este cat ocupa un int – facem sizeof(int) )
fisierBinar.write((char*)&this->id, sizeof(int));
FISIERE BINARE - BOJA

//scriu genul CHAR


fisierBinar.write(&this->gen, sizeof(char));
//scriu media FLOAT (este valoare sau adresa? Este valoare -> punem &)
fisierBinar.write((char*)&this->medieBAC, sizeof(float));
//este olimpic BOOL
fisierBinar.write((char*)&this->esteOlimpic, sizeof(bool));
//tipul ENUM– e valoare (un numar deci &)
fisierBinar.write((char*)&this->tip, sizeof(tipParticular));
//vectori ( int credite[10] , int nrCredite )
//scriu numarul de credite INAINTE DE A SCRIE VECTORUL
fisierBinar.write((char*)&this->nrCredite, sizeof(int));
//scriu valorile creditelor
//am 2 variante de a scris vectorul (fiecare scriu cate una cate una, fie ii scriu pe toti)– un vector
este o zona continua de valori de acelasi tip
//varianta in care scriu tot vectorul (continuu) – printr-o singura operatie
//Ce reprezinta pentru mine vectorul de credite? Care e variabila prin care il gestionam? This
credite este deja pointer!!
//Nu dam & de this credite pentru ca obtinem adresa pointerului, dar pe noi ne intereseaza
valoarea pointerului!! DECI PENTRU POINTERI NU PUNEM & PT CA IMPLICIT OBTII
VARIABILA POINTERULUI, ALTFEL OBTII O ADRESA, NU VALORILE TALE
fisierBinar.write((char*)this->credite, sizeof(int) * this->nrCredite);
//si acum le scriu pe toate prin sizeof*...
//asta e varianta care ma scuteste de for

//scriu numarul de note


fisierBinar.write((char*)&this->nrNote, sizeof(int));
//varianta in care scriu valorile cate una
for (int i = 0; i < this->nrNote; i++) {
fisierBinar.write((char*)&this->note[i], sizeof(int));
} //aici this->note[i] este o valoare si avem nevoie de adresa valorii si punem &
FISIERE BINARE - BOJA

//zona de siruri de caractere


//nume – string
De unde stiu eu unde se termina numele? Si ca trebuie sa citesc 5 caractere? Pentru a face
asta: intotdeauna pt orice valoare care nu are o valoare fix (de ex int are 4 bytes intotdeauna), dar
pt orice vector/sir de caractere, intotdeauna punem inainte numarul de elemente!!
//scriu numarul de caractere al numelui + \0
//definesc o variabila nrDeCaractere (pt ca stringul e un obiect) si punem si \0
int nrCaractereCuTerminator = this->nume.size() + 1;
fisierBinar.write((char*)&nrCaractereCuTerminator, sizeof(int));
//scriu numele cu \0
fisierBinar.write(this->nume.c_str(), nrCaractereCuTerminator * sizeof(char));
//numele e un obiect de tip string si nu avem voie sa punem this->nume, deci numele contine si
anumite atribute si avem nevoie doar de numarul de caractere.
//c_str intoarce un char* , de ce il punem? Pt ca string este o Clasa si ca sa putem extrage ce
avem la acea clasa (numele adica) punem c_str (o privim ca pe o functie care ne returneaza
adresa sirului de caractere).
//size_of(char) = 1;

//prenume char[1000]
//varianta 1 - scriu tot vectorul static (ca oricum e mic – 1000 de caractere)
fisierBinar.write(this->prenume, sizeof(this->prenume));
//numele de vector e mereu pointer (nu scriu nici &-pt ca obtinem adresa pointerului si nu
pointerul in sine, si nu avem nici char pt ca este deja)
//sizeof de pointer intoarce 4, dar mai bine pun sizeof

////varianta 2 - procedam ca in cazul numelui


//nrCaractereCuTerminator = strlen(this->prenume) + 1;
//fisierBinar.write((char*)&nrCaractereCuTerminator, sizeof(int));
////scriu prenume cu \0
//fisierBinar.write(this->prenume, nrCaractereCuTerminator * sizeof(char));
FISIERE BINARE - BOJA

//facultatea char*
//varianta 1 - aleg sa scriu facultatea sub forma unui buffer static de 100 caractere
char buffer[100];
strcpy(buffer, this->facultate);
fisierBinar.write(buffer, sizeof(buffer));//era inmultit cu char, dar char e 1

////varianta 2 - ca in cazul numelui


//nrCaractereCuTerminator = strlen(this->facultate) + 1;
//fisierBinar.write((char*)&nrCaractereCuTerminator, sizeof(int));
//fisierBinar.write(this->facultate, nrCaractereCuTerminator * sizeof(char));
}
MAIN:
//scriere
ofstream fisierDate("studenti.dat", ios::binary | ios::trunc);
if (fisierDate.is_open()) {
s1.scrieStudent(fisierDate);
s2.scrieStudent(fisierDate);
s3.scrieStudent(fisierDate);
fisierDate.close();
}
FISIERE BINARE - BOJA

Citirea este fix in oglinda scrierii


void citireStudent(ifstream& fisierBinar) {
//id-ul
//la valoare avem &, daca era pointer(adresa) nu aveam &
fisierBinar.read((char*)&this->id, sizeof(int));
//citesc genul
fisierBinar.read(&this->gen, sizeof(char));
//citesc media
fisierBinar.read((char*)&this->medieBAC, sizeof(float));
//este olimpic
fisierBinar.read((char*)&this->esteOlimpic, sizeof(bool));
//tipul
fisierBinar.read((char*)&this->tip, sizeof(tipParticular));

VECTORI
//daca e static doar citim, daca e alocat dinamic, trebuie sa alocam!!
//citesc numarul de credite - vector static
fisierBinar.read((char*)&this->nrCredite, sizeof(int));
//citesc creditele - toate odata
fisierBinar.read((char*)this->credite, sizeof(int) * this->nrCredite);

//citesc numarul de note – camp dinamic


fisierBinar.read((char*)&this->nrNote, sizeof(int));
//NU UITA sa aloci vectorul - este dinamic
//evitam memory leak
if (this->note != NULL)
delete[] this->note;
this->note = new int[this->nrNote];
FISIERE BINARE - BOJA

for (int i = 0; i < this->nrNote; i++) { //citim una cate una


fisierBinar.read((char*)&this->note[i], sizeof(int));
}

//citesc numarul de caractere al numelui + \0


int nrCaractereCuTerminator;
fisierBinar.read((char*)&nrCaractereCuTerminator, sizeof(int));
//citesc numele care este in Student stocat intr-un string
char bufferNume[100]; //il citesc intr-un buffer pe care il convertim la string
fisierBinar.read(bufferNume, nrCaractereCuTerminator * sizeof(char));
this->nume = string(bufferNume);//convertim aici

//citesc tot vectorul static (pt ca asa am ales sa il scriem)


fisierBinar.read(this->prenume, sizeof(this->prenume));

//citesc facultatea - atentie este in oglinda cu scrierea


char bufferFacultate[100];
fisierBinar.read(bufferFacultate, sizeof(bufferFacultate));

if (this->facultate != NULL)
delete[] this->facultate;
this->facultate = new char[strlen(bufferFacultate) + 1];
strcpy(this->facultate, bufferFacultate);
}
FISIERE BINARE - BOJA

MAIN: //citire
ifstream fisierStudenti("studenti.dat", ios::binary);
if (fisierStudenti.is_open()) {
Student s4;
s4.citireStudent(fisierStudenti);

cout << endl << " Date din fisier binar ";
cout << s4;

fisierStudenti.close();
}
else
cout << endl << "********************* NU am deschis fisierul !";
}

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