6. diel - Rozdiel medzi textovými a binárnymi subor v C - dodatok
V minulej lekciám, Manipulácia so súbormi a práca s ERROR , sme sa naučili Ďalšie módy Funkcie
fopen ()
a naučili sa pracovať s error. Dnešné, posledná
lekcia, zhrniem Rozdiel medzi textovými a binárnymi subor.
Skoro Ako sa pustíme do samotnej témy, bol by som rád, keby ste si nastavili IDE na normu C99 a aby ste pisala čo najlepšia kód, nastaviť si compilátor tak, že každý warning sa zmení na chybu a compilátor vám nedovolí program scompilovať, kým to nenapravíme.
V Code: Blocks sa to nastavuje takto: Settings -> Compiler and debugger ... -> Other options a tam do okna vložíte: -std = gnu99 -Werror -Wall -lm
V dnešnom článku si povieme prečo a v ktorych prípadoch je výhodné používať na ukladaním dať textové subor a kedy binárnych subor.
Textové a binárne subor
Textové subor maju výhodu, že je možné kedykolvek si
prehliadnuť ich obsah, vytvoriť ich Alebo upraviť bežným editorom. To je
hľa Dôvod, prečo ŠÚ vhodné na ukladaním textu.
Na ukladaním inych dátových robn sa síce Mozu použiť, ale nie je to
výhodné, pretoze napríklad číslo 65535 zaberie v textovom subor priestorov:
5 Byte a v binárnom ľan 2 Byte.
Ďalej nie su vhodné na ukladaním polí, pretoze Medzi jednotlivé prvky póla
este musíme vložiť nejaký separátor, napriklad medzeru a tím je Súbor
automaticky Väčší.
Binárne subor maju nevýhodu, že síce si ich obsah mozme
prehliadnuť napríklad PSPad editorom, ale Niečo v nich meniť je
prinajmenšom nevhodné, pretoze moze viac pokaziť Ako napraviť.
Výhodou je, že ŠÚ vacsinou menšie, rýchlejšími sa s nimi pracuje a pri
ukladaní polí nepotrebujem separátor.
Teraz si dokážeme to, čo som napísal.
Program
Napíšeme si jednoduchý program, ktory Najprv vytvorí pole 50 000 000 integerov. Potom to pole načítať do textového subor a Nakoniec ho načítať do binárneho subor. Každému úkonu sa bude Merati čas a Nakoniec sa výsledky vypíšem.
Založme si nový Project Console application napríklad UlozenieTextBin. PRIDAJ si do projektu dva subor, (source) fce.ca (header) fce.h. Súbor main.c sa vytvorí automaticky.
Najprv si v subor fce.h zadeklarujeme potrebne funkciám a popíšeme ich:
/** fce.h **/ #ifndef FCE_H_INCLUDED // ak nie je súbor načítaný #define FCE_H_INCLUDED // načítaj súbor #define POCET 50000000 // počet prvkov poľa /** * Funkcia zapíše obsah poľa do textového súboru * @param pole premenných typu int * @param reťazec - názov súboru */ void vytvor_txt_subor(int pole[], char* subor); /** * Funkcia zapíše obsah poľa do binárneho súboru * @param pole premenných typu int * @param reťazec - názov súboru */ void vytvor_bin_subor(int pole[], char* subor); #endif // ukončenie podmienky preprocesora
Ďalej si v subor fce.c deklarovanej Funkcie zadefinujeme:
/** funkcie.c **/ #include <stdio.h> #include "fce.h" void vytvor_txt_subor(int pole[], char* subor) { FILE *fw; // deklarácia pointeru na dátový typ FILE fw = fopen(subor, "w"); // otvorenie textového súboru na zápis for (int i = 0; i < POCET; i++) // v cykle sa do súboru fw ukladajú fprintf(fw, "%d ", pole[i]); // integery s medzerou fclose(fw); // uzatvorenie súboru musí byť!!! } void vytvor_bin_subor(int pole[], char* subor) { FILE *fw; fw = fopen(subor, "wb"); // otvorenie binárneho súboru na zápis fwrite(&pole[0], sizeof(int), POCET, fw); // od adresy &pole[0] sa do súboru fw uloží POCET položiek o veľkosti sizeof(int) fclose(fw); // uzatvorenie súboru musí byť!!! }
Nakoniec upravíme Súbor main.c:
/** main.c **/ #include <stdio.h> #include <stdlib.h> #include <time.h> #include "fce.h" int main() { int *pole1; // deklarácia pointera na pole integerov if ((pole1 = (int*)malloc(POCET * sizeof(int))) == NULL) { // dynamická alokácia pamäti s kontrolou printf("Malo pamati!"); return 1; } srand(time(0)); // inicializácia generátora náhodných čísiel printf("Vytvorim pole celych cisiel.\n"); clock_t start1 = clock(); // začiatok merania for (int i = 0; i < POCET; i++) // v cykle vložím do poľa pole1[i] = rand()%200000 + 100000; // náhodné čísla v rozsahu 10 000 - 200 000 clock_t finish1 = clock(); // koniec merania printf("Potrebny cas %.3f secund.\n", (float)((int)finish1 - (int)start1) / CLOCKS_PER_SEC); printf("\nZapisem pole do textoveho suboru.\n"); clock_t start2 = clock(); // začiatok merania vytvor_txt_subor(pole1, "test.txt"); // volanie funkcie clock_t finish2 = clock(); // koniec merania printf("Potrebny cas %.3f secund.\n", (float)((int)finish2 - (int)start2) / CLOCKS_PER_SEC); printf("\nZapisem pole do binarneho suboru.\n"); clock_t start3 = clock(); // začiatok merania vytvor_bin_subor(pole1, "test.dat"); // volanie funkcie clock_t finish3 = clock(); // koniec merania printf("Potrebny cas %.3f secund.\n", (float)((int)finish3 - (int)start3) / CLOCKS_PER_SEC); free(pole1); // uvolnenie pamäti vyčlenenej pre pole return 0; }
Ked project skompilujeme a spustíme dostaneme výstup:
UlozenieTextBin
Vytvorim pole celych cisiel.
Potrebny cas 2.470 secund.
Zapisem pole do textoveho suboru.
Potrebny cas 18.140 secund.
Zapisem pole do binarneho suboru.
Potrebny cas 0.490 secund.
Ako vidíte, Rozdiel v čase zápisu do súborov je obrovský.
Veľkosť súborov:
test.txt
test.dát
Hľa veľkosť súborov je veľmi rozdielna.
Doplníme náš program o načítaním textového a binárneho subor do polí, samozrejme s Meranie času.
Do subor fce.h doplníme deklaráciám nových funkcií:
/** * Funkcia prečíta obsah textového súboru a vloží ho do poľa * @param pole premenných typu int * @param reťazec - názov súboru */ void precitaj_txt_subor(int pole[], char* subor); /** * Funkcia prečíta obsah binárneho súboru a vloží ho do poľa * @param pole premenných typu int * @param reťazec - názov súboru */ void precitaj_bin_subor(int pole[], char* subor);
V subor fce.c. in zadefinujeme:
void precitaj_txt_subor(int pole[], char* subor) { FILE *fr; int i = 0, j; fr = fopen(subor, "r"); while ((fscanf(fr, "%d", &j)) != EOF) { // v cykle číta integery zo súboru pole[i] = j; // a vkladá ich do poľa i++; } fclose(fr); } void precitaj_bin_subor(int pole[], char* subor) { FILE *fr; fr = fopen(subor, "rb"); fread(&pole[0], sizeof(int), POCET, fr); // od adresy &pole[0] vloží zo súboru POCET integerov do poľa fclose(fr); }
A Nakoniec doplníme do subor main.c Nasledujúci kód:
int *pole2; if ((pole2 = (int*)malloc(POCET * sizeof(int))) == NULL) { printf("Malo pamati!"); return 1; } printf("\nPrecitam textovy subor do pola.\n"); clock_t start4 = clock(); // začiatok merania precitaj_txt_subor(pole2, "test.txt"); clock_t finish4 = clock(); // koniec merania printf("Potrebny cas %.3f secund.\n", (float)((int)finish4 - (int)start4) / CLOCKS_PER_SEC); int *pole3; if ((pole3 = (int*)malloc(POCET * sizeof(int))) == NULL) { printf("Malo pamati!"); return 1; } printf("\nPrecitam binarny subor do pola.\n"); clock_t start5 = clock(); // začiatok merania precitaj_bin_subor(pole3, "test.dat"); clock_t finish5 = clock(); // koniec merania printf("Potrebny cas %.3f secund.\n", (float)((int)finish5 - (int)start5) / CLOCKS_PER_SEC);
Aby sme znovu nespustili Vytvorenie póla a jeho zápis do súborov (subor by
sa prepísali), zakomentujeme Prvú časť v subor main.c. Teda všetko čo je
nad riadkom
int * pole2;
Scompilujeme a mozme spustiť. Výstup je:
UlozenieTextBin
Precitam textovy subor do pola.
Potrebny cas 18.570 secund.
Precitam binarny subor do pola.
Potrebny cas 0.390 secund.
A zase vidíte obrovský Rozdiel v časoch citanie jednotlivých
súborov.
To je pre Dnešok všetko.
Projekt je napisane v Code: Blocks na Ubuntu 10.04. Nedá sa OTVORIŤ v Code: Blocks vo Windows, ale jednotlivé subor sa mozu skopírovať a bude to pracovať ai tam. Projekt je priložený.
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 117x (12.09 kB)
Aplikácia je vrátane zdrojových kódov v jazyku C