Înregistrări. Fișiere binare

31.07.2019 Photoshop

În exemplul de mai sus, opțiunea „cea mai lungă” este „b”: necesită 23 de octeți (21 de octeți pentru șir și 2 octeți pentru număr întreg). Opțiunile „n” și „m” necesită 4 și, respectiv, 5 octeți (vezi tabelul).

nume, articol editor Partea varianta

Fișiere binare

Fișierele binare stochează informații în forma în care acestea sunt prezentate în memoria computerului și, prin urmare, sunt incomode pentru oameni. Privind un astfel de fișier, este imposibil de înțeles ce este scris în el; nu poate fi creat sau corectat manual - într-un editor de text - etc. Cu toate acestea, toate aceste inconveniente sunt compensate de viteza de lucru cu datele.

În plus, fișierele text sunt clasificate ca structuri de acces secvențial, în timp ce fișierele binare sunt clasificate ca structuri de acces direct. Aceasta înseamnă că în orice moment puteți accesa oricine, nu doar elementul curent al fișierului binar.

Fișiere tastate

Variabilele tipurilor de date structurate (cu excepția șirurilor de caractere) nu pot fi citite fișier text. De exemplu, dacă trebuie să introduceți date dintr-un fișier text pentru a completa înregistrarea jucăriilor cu informații despre jucăriile disponibile pentru vânzare (numele produsului, prețul produsului și intervalul de vârstă pentru care este destinată jucăria):

varsta: set de 0..18; (specificat în dosar prin limite)

atunci va trebui să scrieți următorul cod:

c:char; i,j,min,max: întreg;

a: gamă de jucării;

start assign(f,input); resetare(f);

pentru i:=1 la 100 face dacă nu eof(f)

apoi cu a[i] do

începe readln(f,nume,preț,min,max); varsta:=;

pentru j:= min la max do age:=varsta+[j];

După cum puteți vedea, o astfel de citire element cu element este foarte incomod și necesită multă muncă.

Se oferă o cale de ieșire din această situație fișiere tastate- elementele lor pot aparține oricărui tip de date de bază sau structurate. Singura restricție este că toate elementele trebuie să fie de același tip. Acest aparent inconvenient este

o condiție indispensabilă pentru organizarea accesului direct la elementele unui fișier binar: ca și în cazul tablourilor, dacă lungimea fiecărei componente a structurii este cunoscută exact, atunci adresa oricărei componente poate fi calculată folosind o formulă foarte simplă:

<начало_структуры> + <номер_компонента>*<длина_компонента>

Descrierea fișierelor tastate

În secțiunea var există variabile de fișier concepute pentru a funcționa fișiere tastate, sunt descrise după cum urmează:

var<файловая_перем>: dosar de<тип_элементов_файла>;

Nicio variabilă de fișier nu poate fi specificată ca constantă.

Scopul unui fișier tastat

De acum înainte și până la sfârșitul secțiunii, prin cuvântul „dosar” vom înțelege „ fișier tip binar" (desigur, dacă nu se specifică altfel).

Echipă atribui(f,"<имя_файла>"); servește la stabilirea unei conexiuni între variabila fișier f și numele fișierului pentru care această variabilă va fi responsabilă de lucru.

linia "<имя_файла>" poate conține calea completă către fișier. Dacă calea nu este specificată, fișierul este considerat a fi localizat în același director cu modulul executabil al programului.

Deschiderea și închiderea unui fișier tastat

În funcție de acțiunile pe care programul dvs. va efectua cu fișierul deschis, acesta poate fi deschis în două moduri:

resetare(f); - deschiderea unui fișier pentru a citi informații din acesta și în același timp pentru a scrie în el (dacă un astfel de fișier nu există, încercarea de a-l deschide va provoca o eroare). Aceeași comandă este folosită pentru a returna un pointer la începutul fișierului;

rescrie(f); - deschiderea unui fișier pentru a-i scrie informații; dacă un astfel de fișier nu există, acesta va fi creat; dacă un fișier cu același nume există deja, toate informațiile conținute anterior în acesta vor dispărea.

Se închid fișiere tastate procedura close(f), comună tuturor tipurilor de fișiere.

Citirea dintr-un fișier tastat

Citirea dintr-un fișier care este deschis pentru citire se face folosind comanda read(). În paranteze, este indicat mai întâi numele variabilei fișierului, apoi lista de intrare1):

Puteți introduce doar variabile de tipul corespunzătoare declarației dintr-un fișier, dar acest tip de date poate fi și structurat. Să spunem, dacă revenim la exemplul dat la începutul paragrafului ". Fișiere tastate„, va deveni evident că utilizarea fișier tastatîn loc de text va reduce semnificativ textul programului:

tip toy = nume de înregistrare: șir; pret: real;

varsta: set de 0..18; (definit de granițe)

var f: dosar de jucărie;

a: gamă de jucării; ÎNCEPE

assign(f,input);

pentru i:=1 până la 100 do

dacă nu eof(f) atunci citiți(f,a[i]); aproape(f);

Căutați într-un fișier tastat

Funcția eof(f:file):boolean, deja familiară nouă, raportează când s-a ajuns la sfârșitul fișierului. Toate celelalte funcții „termină căutare” (eoln(), seekeof() și seekeoln()) inerente fișierelor text nu pot fi aplicate fișierelor tastate.

Dar există subrutine speciale care vă permit să lucrați fișiere tastate ca și în cazul structurilor cu acces direct:

1. Funcția filepos(f:file):longint va raporta poziția curentă a pointerului în filef. Dacă indică la sfârșitul unui fișier care conține N elemente, atunci această funcție va returna rezultatul N . Acest lucru este ușor de explicat: elementele fișierului sunt numerotate începând de la zero, deci ultimul element este numerotat N-1. Și numărul N aparține astfel unui element „inexistent” - un semn al sfârșitului fișierului.

2. Funcția filesize(f:file):longint va calcula lungimea fișierului f .

3. Procedura seek(f:file,n:longint) va muta indicatorul din fișierul f la începutul numărului de înregistrare N . Dacă se dovedește că n este mai mare decât lungimea reală a fișierului, atunci indicatorul va fi mutat dincolo de sfârșitul actual al fișierului.

4. Procedura truncate(f:file) va tăia „coada” fișierului: toate elementele de la curent până la sfârșitul fișierului vor fi eliminate din acesta. De fapt, doar semnul „sfârșitul fișierului” va fi rescris în locul în care a indicat indicatorul, iar valorile „decupate” fizic vor rămâne în locurile lor originale - vor deveni pur și simplu „orfani”.

Scrierea într-un fișier tastat

Puteți salva variabile într-un fișier care este deschis pentru scriere folosind comanda write(). Ca și în cazul citirii, variabila fișier este listată mai întâi, urmată de lista de ieșire:

scrie (f,a,b,c); - scrieți în fișierul f (deschis anterior pentru scriere cu comenzile rewrite (f) sau reset (f) ) variabilele a , b , c .

Ieșire către fișier tastat Sunt permise numai variabilele care se potrivesc cu descrierea tipului de date. Constantele fără nume și netipărite nu pot fi tipărite

fișier tastat.

Fișiere tastate sunt considerate atât structuri de acces direct cât și secvenţial. Aceasta înseamnă că scrierea este posibilă nu numai la sfârșitul fișierului, ci și la orice alt element. Valoarea scrisă va înlocui valoarea anterioară în acest element (vechea valoare va fi „suprascrisă”).

De exemplu, dacă trebuie să înlocuiți al cincilea element al unui fișier cu valoarea stocată în variabila a, atunci veți scrie următorul fragment de program:

caută(f,5); (indicatorul va fi setat la începutul celui de-al 5-lea element)

scrie (f,a); (indicatorul va fi setat la începutul celui de-al 6-lea element)

înregistrări), atunci este destul de de înțeles să vrei să reducă cumva spațiul de memorie neutilizat, dar ocupat.

Mai ales pentru astfel de cazuri există înregistrări cu parte variantă.

Descrierea înregistrării cu partea variantă

In sectiunea var înregistrare cu parte variantă descris astfel:

var<имя_записи>:înregistra<поле1>: <тип1>; [<поле2>: <тип2>;] [...] caz<поле_переключатель>: <тип>de<варианты1>: (<поле3>: <тип3>; <поле4>: <тип4>; ...); <варианты2>: (<поле5>: <тип5>; <поле6>: <тип6>;

...);[...] Sfârşit; Piesa nevariantaînregistrări (până la cuvânt cheie. În general, partea nevariantă poate fi complet absentă.

Partea variantaîncepe cu cuvântul caz rezervat, după care este indicat câmpul de înregistrare, care va servi ulterior ca comutare. Ca și în cazul unei declarații de caz obișnuite, comutatorul trebuie să aparțină unuia dintre tipuri de enumerare date (vezi prelegerea 3). Lista de opțiuni poate fi o constantă, un interval sau uniunea mai multor constante sau intervale. Setul de câmpuri care trebuie incluse în structura înregistrării dacă se execută opțiunea corespunzătoare este cuprins între paranteze.

Exemplu. Pentru a descrie conținutul bibliotecii, sunt necesare următoarele informații:

Coloanele „Titlu” și „Editor” sunt comune tuturor celor trei opțiuni, iar câmpurile rămase depind de tipul de publicație. Pentru implementarea acestei structuri vom folosi înregistrare cu o parte variantă:

tip biblio = nume înregistrare,editor: șir;

item case: char of "b": (autor: șir; an: 0..2004);

"n": (date: data);

"m": (anul: 1700..2004; luna: 1..12; număr: întreg); Sfârşit; înregistrare cu parte variantăÎn funcție de valoarea câmpului articolului, înregistrarea va conține fie 4, 5 sau 6 câmpuri.

Mecanism de utilizare a unei înregistrări cu o parte variantă

Numărul de octeți alocați de compilator pentru , este determinată de versiunea sa „cea mai lungă”. Seturile „mai scurte” de câmpuri din alte opțiuni ocupă doar o parte din memoria alocată. Partea varianta
... În exemplul de mai sus, opțiunea „cea mai lungă” este „b”: necesită 23 de octeți (21 de octeți pentru șir și 2 octeți pentru număr întreg). Opțiunile „n” și „m” necesită 4 și, respectiv, 5 octeți (vezi tabelul). nume, editor articol
... "b" autor
... an articol "n" date
... În exemplul de mai sus, opțiunea „cea mai lungă” este „b”: necesită 23 de octeți (21 de octeți pentru șir și 2 octeți pentru număr întreg). Opțiunile „n” și „m” necesită 4 și, respectiv, 5 octeți (vezi tabelul). nume, editor articol

Fișiere binare

"m"

lună număr Fișierele binare stochează informații în forma în care sunt prezentate în memoria computerului și, prin urmare, sunt incomode pentru oameni. Privind într-un astfel de fișier, este imposibil să înțelegeți ce este scris în el; nu poate fi creat sau corectat manual - într-un editor de text - etc. Cu toate acestea, toate aceste inconveniente sunt compensate de viteza de lucru cu datele.

În plus, fișierele text sunt clasificate ca structuri

acces secvenţial , și binar - direct. Aceasta înseamnă că oricând poți accesa orice element, nu doar elementul curent. Fișierele binare diferă de fișierele text numai prin metodele de lucru cu acestea. De exemplu, dacă scriem numărul „4” într-un fișier text, atunci acesta este scris ca un caracter și este nevoie de un octet pentru a-l stoca. În consecință, dimensiunea fișierului va fi egală cu un octet. Un fișier text care conține intrarea: „145687” va avea dimensiunea de șase octeți.

Dacă scrieți numărul întreg 145.687 într-un fișier binar, atunci acesta va avea o dimensiune de patru octeți, deoarece este necesar pentru a stoca datele. tastați int. Adică, fișierele binare sunt mai compacte și, în unele cazuri, mai ușor de procesat.

Scrierea tipurilor de date standard în fișiere binare

Pentru a deschide un fișier binar, trebuie să setați modul de acces la ios::binary (în unele compilatoare C++, ios::bin).

Pentru a crea un fișier de ieșire, creați un obiect:

ofstream outBinFile("out.bin", ios::out | ios::binary);

/* crearea unui obiect de clasă ofstream afară. coșul de gunoi

dacă (! out_f i 1) //verificare standard

Datele sunt scrise folosind metoda write(), care are doi parametri: primul este un pointer la începutul (adresa de pornire) a datelor care sunt scrise, al doilea este numărul de octeți care trebuie scrisi. În acest caz, indicatorul trebuie convertit în mod explicit la tipul char.

Exemplul 1. Scrieți variabile de diferite tipuri într-un fișier binar:

ofstream outBinFile ("test.bin", ios::out I

ios: :binar) ; /^crearea unui obiect de clasă de pârâu și încercând să-l conecteze la un fișier test. coșul de gunoi în modul de scriere a fișierelor binar */

int a - 145687; //declararea unei intregi variabile O

outBinFi le. scrie ((car*) &a, sizeof (a)) ; /^ scrie în fișier

variabilă O ca un flux de octeți, adică scrierea într-un fișier a reprezentării interne a întregii variabile a */ float x - 123,25; // declararea unei variabile reale X

outBinFile .write ((car*) &x, sizeof (x)) ; /^ scrie în fișier

variabilă X ca un flux de octeți, adică scrierea într-un fișier a reprezentării interne a întregii variabile x*/

//definirea unei variabile simbolice Cu şi iniţializandu-l cu simbolul g outBinFile.write((char*)&c, sizeof(c));

//înregistrați un simbol g a dosar

outBinFile.close(); returnează 0;

Dacă deschideți conținutul fișierului .bin de testare cu un editor de text, acesta va arăta astfel:

iar dimensiunea fișierului va fi de 9 octeți.

Citirea tipurilor de date standard de la fișiere binare

Pentru a deschide un fișier binar existent pentru citire, trebuie să creați un obiect:

ifstream inpBinFile("inp.bin", ios::in I ios::binary);

/* folosim o disjuncție de steaguri care indică faptul că fișierul este deschis pentru citire în formă binară */

dacă (! inpBinFile)

coutPentru a citi datele, folosim funcția read(), care are parametri similari cu funcția write().

#include folosind namespace std; int main()

ifstream inpBinFile("test.bin", ios::in I

ios::binar); / / deschide fișierul pentru citire în formă binară

int a; float x; char c = "g";

inpBinFile.read((char*)&a, sizeof(a));

//citește o variabilă întreagă inpBinFile.read((char*)&x, sizeof(x));

//citește o variabilă reală inpBinFile.read((char*)&c, sizeof (c));

//citește o variabilă simbolică

inpBinFile.close(); cout

Rezultatul programului:

a = 145687 x = 123,25 s = g

Vă rugăm să rețineți că nu are loc conversie de informații atunci când utilizați funcțiile de scriere și citire. Reprezentarea internă a datelor este scrisă și citită din fișier. De aceea cele două programe anterioare au dat rezultatul corect.

Scrie și citește tipuri personalizate date în fișiere binare

Spre deosebire de fișierele text, lucrul cu tipuri de date personalizate folosind fișiere binare nu este diferit de tipurile de date standard. Metodele write() și read() sunt utilizate în mod similar. Programatorul trebuie doar să indice adresa secțiunii de memorie care urmează să fie scrisă și numărul de octeți care urmează să fie scris, ținând cont că nu are loc conversie de date, se scrie și se citește doar reprezentarea internă a informațiilor.

De asemenea, atunci când lucrați cu fișiere binare, se pot folosi metodele seekg(), tellg(), seekp(), tellp().

Exemplul 3. Scrieți un program care scrie informații despre un grup de turiști într-un fișier binar.

fstream BinFile("ankety.bin", ios::in I ios::out | ios::binary);

Anketa Gruppa = ; pentru (int i = 0; i

BinFile.write((char*)&Gruppa[i], sizeof(Anketa)); BinFile.close(); returnează 0;

Exemplul 4. Fișierul „ankety.bin” conține date despre un grup de turiști, este necesar să îl citiți și să îl afișați pe ecran.

#include folosind namespace std; struct chestionar (

nume char; int vârsta;

tip de date structurale Chestionar la ecran*/

ostream& operator

fstream BinFile("ankety.bin", ios::in | ios::out | ios::binary); dacă (!BinFile)

pentru (int i = 0; i

//citește toți octeții ocupați simultan tip variabil Anketa BinFile.read((char*)&Gruppa[i], sizeof(Anketa));

BinFile.close(); returnează 0;

Rezultatul programului:

Ivanov, 23 Sidorov, 21 Petrov,22

Pentru a continua, apăsați orice tastă. . .

Dezvoltarea propriilor clase pentru lucrul cu fișiere

Este incomod să folosești în mod constant metodele write() și read() este mult mai plăcut să poți folosi operațiunile „>” prin analogie cu fișierele text; Să dăm un exemplu de implementare a clasei noastre pentru lucrul cu fișiere binare.

folosind namespace std;

struct Chestionar //declară o structură pentru stocarea informațiilor

/*supraîncărcați operația de inserare într-un flux pentru ieșire personalizată

tip de date structurale Chestionar la ecran*/

ostream& operator

clasa outBinaryFile: public of stream /^ definește clasa noastră pentru lucrul cu fișiere binare de ieșire. O derivăm din clasa pentru lucrul cu fluxuri de fișiere de ieșire */

/*când descrieți constructorul unei clase generate, nu uitați să apelați constructorul clasei de bază, trecându-i parametrii necesari*/

outBinaryFile(car* nume): ofstream(nume, ios::out I ios::binar)

//supraîncărcați operațiile necesare ca metode de clasă operator outBinaryFile&

scrie((char*)&chislo, sizeof(chislo)); returnează *aceasta;

operator outBinaryFile&

scrie((car*)&ank, sizeof(ank)); returnează *aceasta;

clasa inpBinaryFile: public if stream /* Definim clasa noastră pentru lucrul cu fișiere binare de intrare. O derivăm din clasa pentru lucrul cu fluxuri de fișiere de intrare */

inpBinaryFile(char* name): ifstream(nume, ios::in I ios::binary)

/*apelarea constructorului clasei de bază cu parametrii necesari,

suficient pentru constructorul clasei derivate */

//supraîncărcați operațiunile necesare

inpBinaryFile& operator >> (int& number)

read((char*)&chislo, sizeof(chislo)); returnează *aceasta;

inpBinaryFile& operator >> (Anketa& ank)

read((char*)&ank, sizeof(ank)); returnează *aceasta;

int a = 111, b = 112; outBinaryFile outFile("dannye.bin");

//deschideți fișierul pentru citire

inpBinaryFile inpFile("dannye.bin"); dacă (!inpFile)

pentru (int i = 0; i

inpFile >> a; //citește profilul din fișier

cout //și afișează-l pe ecran

inpFile >> chestionar; cout

Rezultatul programului:

Kolya, 1990, 582-78-95.

Pentru a continua, apăsați orice tastă. . .

1. Este posibil să folosiți o operație într-un program?

ios::in I ios::out

  • a) da, în orice caz;
  • b) da, dar numai atunci când lucrați cu fișiere text;
  • c) nu, în orice caz.
  • 2. Specificați opțiunea corectă pentru deschiderea unui fișier text pentru citire:
    • a) ifstream inpF("input.txt", ios::in);
    • b) ifstream inpF("input.txt", ios::input);
    • c) ifstream inpF(ios:in, "input.txt").

H. Ce va fi afișat pe ecran ca urmare a executării următorului cod?

inputFile.get(c);

următorul - inputFile.peek();

dacă (următorul == EOF)

  • a) conținutul fișierului asociat fluxului inputFile va fi afișat pe ecran o dată;
  • b) conținutul fișierului asociat fluxului inputFile va fi afișat pe ecran de un număr infinit de ori;
  • c) nu va fi afișat nimic pe ecran.
  • 4. Câte caractere sunt în fișier?
  • 12 3 4 5 6
  • a) 6;
  • b) 7;
  • c) 11.
  • 5. Ce metode vă permit să determinați sfârșitul unui fișier?
  • a) eof();
  • b) bun();
  • c) ambele metode.
  • 6. Care este scopul funcției getline()?
  • a) citește un cuvânt dintr-un fișier;
  • b) citește întregul conținut al fișierului;
  • c) citește o linie dintr-un fișier.
  • 7. Pentru a scrie/citi tipuri de date personalizate într-un fișier, trebuie să:
    • a) supraîncărcați operațiunile „>>” și ​​„
    • b) scrierea și citirea tipurilor de date personalizate sunt disponibile fără acțiuni suplimentare;
    • c) scrierea și citirea tipurilor de date personalizate în fișier este imposibilă.
  • 8. Ce funcții sunt folosite pentru a scrie/citi informații în formă binară?
  • a) printf / scanf;
  • b) scrie/citește;
  • c) pune/primi.
  • 1. Scrieți un program care scrie literele alfabetului englez într-un fișier.
  • 2. Fișierul input.txt conține informații de la mai multe șiruri de text. Afișați conținutul acestui fișier pe ecran, numărați numărul de linii din fișier.
  • 3. Discul conține fișierul result.txt cu rezultatele experimentelor chimice. Scrieți un program care creează o copie a acestui fișier numit copy_resylt.txt.
  • 4. Introduceți numele fișierului folosind tastatura. Ștergeți toate liniile pare din fișierul specificat.
  • 5. Scrieți un program care înlocuiește totul dintr-un fișier text litere mici cu majuscule și invers.
  • 6. Fișierul text sursă conține numere separate prin spații. Generați două fișiere noi: primul ar trebui să conțină numai numere pare, iar al doilea - impar.
  • 7. Fișierul conține numere reale. Scrieți un program care aruncă partea fracționară a acestor numere și le scrie într-un fișier nou.
  • 8. Un fișier text conține informații despre zborurile companiilor aeriene. Selectați zborurile care pleacă după-amiaza din aceste date și afișați-le pe ecran.
  • 9. Supraîncărcați >> și operatorii
  • 10. Scrieți propria clasă pentru a lucra cu fișiere binare.
  • 11. Scrieți lista celor 10 elevi din clasă într-un fișier text și într-un fișier binar. Comparați aceste fișiere. Explicați diferența rezultată.
  • 12. Dezvoltați o clasă care scrie informații despre mașini (an de fabricație, marca, culoare etc.) într-un fișier text. În acest caz, fiecare simbol de informare este înlocuit cu propriul său cod ABO 1. Afișați fișierul rezultat pe ecran.

Întrebări de securitate

  • 1. Ce clase sunt folosite pentru a lucra cu fluxuri de fișiere?
  • 2. Ce moduri de acces pot fi folosite atunci când lucrați cu fișiere? Dați exemple.
  • 3. Ce metodă este folosită pentru a deschide un fișier? Dați exemple.
  • 4. Ce operațiuni sunt disponibile pentru lucrul cu fișiere? Ce funcții sunt prevăzute pentru efectuarea acestor operații?
  • 5. Ce metode vă permit să determinați sfârșitul unui fișier atunci când citiți informații din acesta? Care este diferența dintre aceste metode? Dați exemple.
  • 6. Cum puteți citi variabilele tipurilor de date standard din fișierele text?
  • 7. Este posibil să citiți variabile de tip de date personalizate din fișierele text?
  • 8. Ce funcții sunt concepute pentru a citi aleatoriu informații dintr-un fișier? Dați exemple.
  • 9. Denumiți caracteristicile fișierelor binare. Care sunt avantajele utilizării unor astfel de fișiere?
  • 10. Ce funcții pot fi folosite pentru a scrie/citi informații în fișiere binare?
  • 11. Cum se citesc variabilele tipurilor de date standard dintr-un fișier binar?
  • 12. Ce considerații trebuie luate în considerare atunci când citiți tipuri de date personalizate din fișiere binare?
  • „Ivanov”, 23), („Sidorov”, 21),

Probabil că ați întâlnit deja termenii „text” și „binar” în timp ce citiți câteva articole despre . Și au decis că toate acestea sunt prea complicate pentru tine, că nu va fi niciodată posibil să-ți dai seama, așa că nu s-au adâncit în el, renunțând la el.

Vom încerca să explicăm totul cât mai mult posibil. într-un limbaj simplu, pentru că astfel de informații sunt utile pentru fiecare utilizator, chiar și pentru cel mai neexperimentat, deoarece sunt direct legate de elementele de bază ale securității computerului.

Puțină teorie

Fișierul text conține caractere ASCII (abrevierea înseamnă American Cod standard pentru Information Interchange, ceva de genul „Standard american de codificare pentru schimbul de informații”).

De fapt, ASCII este un tabel în care fiecărei litere, număr, semn de punctuație și diverși „câini” cu „fulgi de zăpadă” (în sensul de @ și *) sunt alocați câte un octet. Adică opt zerouri și unu (biți). În plus, desigur, controlează personaje precum noua linie.

Program pentru deschiderea fișierelor din caractere ASCII convertește octeții în litere, numere și alte caractere imprimabile pe afișaj. Desigur, software-ul trebuie să înțeleagă acea parte a tabelului care corespunde limbii ruse, dar aceasta este deja o chestiune de codificare.

Într-un fișier binar, zerourile și unurile sunt aranjate în secvențe care nu sunt neapărat necesare pentru afișarea textelor (deși există unele, de exemplu, *doc). De ce, întrebi. Răspunsul este simplu: pentru orice altceva. Programe, filme, muzică, imagini - fiecare format are propriile sale principii structurale de organizare a datelor.

Cuvântul „binar” în sine înseamnă „format din două componente”, „dublu”. Într-adevăr, este posibil să definiți clar doar două componente - zero și unu, biți, „cărămizi” din care este compus fișierul. Semnificația tuturor celorlalte poate apărea doar în timpul pornirii (deschidere, redare).

Partea greșită a lumii digitale

Puteți căuta în interiorul fișierului binar folosind program special- Editor HEX. (Din cuvântul Hexazecimal, care denotă sistemul numeric hexazecimal.) Un astfel de software arată octeții sub forma denumirilor lor HEX, care sunt de fapt localizați și sub forma unui tabel (matrice).

De exemplu, octeții de imagine în format JPEG, o fotografie sau o fotografie obișnuită, va fi afișată în fereastra editorului ca FF D8 FF 00 04 3A 29 și așa mai departe.

Un specialist va înțelege că secvența de octeți FF D8 de la început indică faptul că acesta este un JPEG. Dar toate acestea nu sunt atât de interesante pentru nespecialiști.

De asemenea, puteți deschide un fișier text într-un editor HEX pentru a vedea ce octeți corespund unor anumite litere (caractere ASCII). Dar doar din curiozitate, tot nu are rost.

Dar fișierele binare sunt uneori vizualizate în format hexazecimal pentru scopuri destul de semnificative și specifice. De exemplu, specialiștii din laboratorul antivirus caută cod rău intenționat, adăugată la cea principală. Apropo, să trecem la problemele de securitate.

Ce poate dăuna

Un fișier text nu poate conține altceva decât caractere ASCII. Cu toate acestea, programele nu sunt doar binare, ci și constau din simbolurile de mai sus. Mă refer la scenarii, desigur.

Cu alte cuvinte, fișierul *txt nu este infectat în principiu și nu reprezintă o amenințare. Și dacă există un script în interiorul unui fișier text, atunci poate cauza multe probleme.

De exemplu, fișierul *bat conține codul diferitelor comenzi și este lansat făcând dublu clic, cum ar fi program regulat. Acele comenzi sunt scrise cu caractere ASCII, dar sistemul de operare știe să le interpreteze - transformă-le în zerouri și în unele tipice pentru programe.

Dar, desigur, nu dați clic pe fișiere bat necunoscute, nu? Asta e bine.

Publicații anterioare:

Ultima modificare: 06-11-2012 14:45:16

Etichete materiale: ,

Exemplele pe care le-am luat în considerare până acum au demonstrat intrarea/ieșirea formatată a informațiilor în fișiere. Este recomandabil să utilizați fișiere formatate de intrare/ieșire a numerelor numai atunci când acestea sunt mici ca dimensiune și cantitate, precum și atunci când este necesar să se asigure posibilitatea de a vizualiza fișiere fără software. Altfel, desigur, este mult mai eficient să folosiți I/O binare, în care numerele sunt stocate în același mod ca în OP-ul computerului, mai degrabă decât ca șiruri de caractere. Permiteți-mi să vă reamintesc că o valoare întreagă (int) sau reală (float) ocupă 4 octeți în memorie, o valoare dublă ia 8 octeți, iar o valoare char ia 1 octet. De exemplu, numărul 12345 dintr-un fișier text (formatat) are 5 octeți, iar într-un fișier binar are nevoie de 4 octeți.

Fișiere binare, adică fișierele în care informațiile sunt stocate într-o formă de reprezentare internă sunt utilizate pentru utilizare ulterioară de către software; Avantajul fișierelor binare este că, în primul rând, la citire/scriere, nu se pierde timpul la conversia datelor din forma simbolică de reprezentare în cea internă și invers și, în al doilea rând, nu există pierderi de precizie. numere reale. Atât în ​​cazul intrării/ieșirii formatate, cât și în cazul intrării/ieșirii binare, pentru a procesa „corect” informații dintr-un fișier, trebuie să știți ce tipuri de date, cum și în ce secvență sunt scrise în fișier binar, mai ales că vizualizarea unui fișier binar folosind editor de text nu va da nimic.

Să luăm în considerare un exemplu care demonstrează scrierea elementelor întregi ale unui tablou dinamic într-un fișier binar și citirea lor din acest fișier.

#include

#include

#include

folosind namespace std;

cout<< "Vvedite kol-vo elementov celochisl. massiva: "; cin >> N;

int *mas = new int [N];

pentru(i=0; i

cout<< " Vvedite " << i << "-i element: "; cin >> mas[i];

cout<< "\nIdet zapis dannyh v fail..." << endl;

ofstream fout("c:\\os\\bin.dat", ios::binary);//creat Ieșire flux binar

if(!fout) ( cout<< "\n Oshibka otkrytiya faila!"; getch(); return 1; }

fout.write(reinterpret_cast (mas), N*sizeof(int));// scrieți matrice în fișier

fout.close();//închiderea fluxului

cout<< "Dannye uspeshno zapisany!" << endl;

pentru(i=0; i

ifstream fin("c:\\os\\bin.dat", ios::binary); //creez un thread pentru a citi fișierul

if(!fin) ( cout<< "\n Oshibka otkrytiya faila!"; getch(); return 1; }

cout<< "Fail sodergit:" << endl;

fin.read(reinterpret_cast (mas), N*sizeof(int));//citește matricea din fișier

pentru(i=0; i

getch(); returnează 0;

În acest program, o atenție deosebită trebuie acordată utilizării funcțiilor write() (metoda clasei ofstream) și read() (metoda clasei ifstream). Aceste funcții gândesc datele în termeni de octeți și sunt concepute pentru a transfera un anumit număr de octeți dintr-un buffer de date într-un fișier și înapoi. Parametrii acestor funcții sunt adresa tampon și lungimea acesteia în octeți.

Funcția write() este concepută pentru a scrie într-un fișier numărul de octeți specificat în al doilea parametru dintre cei specificați în primul parametru adrese tampon de date, iar funcția read() este concepută pentru a citi datele dintr-un fișier. Trebuie remarcat aici că aceste funcții funcționează numai cu un buffer de date de tip char. În acest sens, în acest program am folosit operatorul reinterpret_cast<> care convertește tamponul nostru de date de tip int (mas) într-un tampon de tip char.

Este important de reținut că turnarea folosind operatorul reinterpret_cast necesar numai în cazurile în care primul parametru al funcţiilor scrie() Şi citire() nu este o matrice de caractere (la urma urmei, un caracter de tip char durează doar 1 octet).În plus, dacă trebuie să scrieți sau să citiți nu o matrice, ci variabile individuale, atunci trebuie să utilizați un mecanism de referință (un link către adresa buffer-ului de date), de exemplu:

ofstream fout(nume fișier, ios::app | ios::binary);

fout.write(reinterpret_cast (& cb), sizeof(float));

Acum este necesar să discutăm al doilea parametru al funcțiilor luate în considerare. În acest program, ca al doilea parametru am folosit expresia N*sizeof(int), cu care am calculat numărul de octeți. De exemplu, dacă avem 5 elemente de matrice întregi, atunci numărul de octeți va fi 20. Funcția sizeof() returnează numărul de octeți alocați pentru tipul de date specificat ca parametru. De exemplu, sizeof( int) va reveni 4.

Deci, programul dat în acest exemplu vă permite să scrieți date în formă binară în fișierul bin.dat și să le citiți din acest fișier binar. Mai mult decât atât, după citire, aceste date sunt convertite în tipul int, capătă o structură matrice și orice operație poate fi efectuată cu aceasta.

Acum, imaginați-vă că trebuie să scrieți un program care vă permite să citiți date din fișierul bin.dat și știm doar că acest fișier conține elementele unui tablou întreg în formă binară. Numărul de elemente scrise ( N ) nu știm. Când creăm un program, nu avem dreptul de a folosi o matrice constantă, adică. alocați-i memorie în etapa creării programului. Acest lucru va duce la un rezultat eronat. Deoarece o valoare prea mică pentru N va avea ca rezultat nu toate elementele matricei să fie numărate, iar o valoare prea mare pentru N va duce la umplerea celulelor suplimentare cu valori aleatorii.

Să luăm în considerare un exemplu de program care vă permite să citiți elementele unui tablou întreg dintr-un fișier binar prin alocarea dinamică a memoriei și, pentru a demonstra realismul datelor citite, calculați suma acestora.

#include

#include

#include

folosind namespace std;

int N, i, sum=0, dfb; //dfb - lungimea fișierului în octeți

ifstream fin("c:\\os\\bin.dat", ios::binar);

if(!fin) ( cout<< "Oshibka otkrytiya faila!"; getch(); return 1; }

fin.seekg(0, ios::end);//setează poziția de citire la sfârșitul fișierului (0 octeți de la sfârșit)

dfb = fin.tellg();//obține valoarea sfârșitului poziției fișierului (în octeți)

N=dfb/4;//știind că un număr întreg are 4 octeți, calculează numărul de numere

int *arr = int nou [N];//creează o matrice dinamică

fin.seekg(0, ios::beg);//înainte de a citi datele, mutați poziția curentă la începutul fișierului

fin.read(reinterpret_cast (arr), dfb);

cout<< "Iz faila schitano " << N << " elementov:" << endl;

pentru(i=0; i

pentru(i=0; i

cout<< "\n Ih summa = " << sum;

getch(); returnează 0;

Să aruncăm o privire mai atentă la acest program, în care am folosit activ funcțiile seekg() și tellg(), care sunt metode ale clasei ifstream. Trebuie remarcat aici că Orice fișier atunci când este deschis este asociat cu o așa-numită poziție curentă de citire sau scriere. Când un fișier este deschis pentru citire, această poziție implicită este setată la începutul fișierului. Dar destul de des este necesar să controlați manual poziția pentru a putea citi și scrie pornind de la o locație arbitrară din fișier. Funcțiile seekg() și tellg() vă permit să setați și să verificați indicatorul de citire curent, în timp ce funcțiile seekp() și tellp() fac același lucru pentru pointerul de scriere.

Metoda seekg(1_parameter, 2_parameter) mută poziția curentă de citire din fișier cu numărul de octeți specificat în parametrul 1 în raport cu locația specificată în parametrul 2. 2_parameter poate lua una dintre cele trei valori:

ios::beg – de la începutul fișierului;

ios::cur – din poziția curentă;

ios::end – de la sfârșitul fișierului.

Aici beg, cur și end sunt constante definite în clasa ios, iar simbolurile:: reprezintă operația de acces la această clasă. De exemplu, operatorul fin.seekg(-10, ios::end); vă permite să setați poziția curentă de citire dintr-un fișier la 10 octeți înainte de sfârșitul fișierului.

Acum să revenim la descrierea funcționării programului. Pe baza faptului că nu știm numărul de numere scrise în fișier, trebuie mai întâi să aflăm numărul de numere. Pentru a face acest lucru, folosind fin.seekg(0, ios::end); trecem la sfârșitul fișierului și, folosind funcția tellg(), returnăm lungimea fișierului în octeți variabilei dfb. Funcția tellg() returnează poziția curentă a indicatorului în octeți. Deoarece știm lungimea unui număr întreg în octeți (4 octeți), este ușor să calculăm numărul de numere scrise în fișier, cunoscând lungimea fișierului în octeți ( N=dfb/4;). După ce am aflat numărul de numere, creăm o matrice dinamică și trecem la începutul fișierului pentru a începe să citim datele folosind funcția read(). După ce numărul specificat de octeți de date (dfb) este transferat în bufferul de date (arr), datele citite în acest fel capătă o structură matrice și devin pe deplin potrivite pentru orice operațiuni și transformări de cod.