IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 6 - Rozdíly mezi textovými a binárními soubory v jazyce C

V minulé lekci, Manipulace se soubory a práce s errory v jazyce C, jsme se naučili další módy funkce fopen() a také pracovat s errory.

Dnešné, posledná lekcia, zhŕňa rozdiely medzi textovými a binárnymi súbormi.

Skôr ako sa pustíme do samotnej témy, bol by som rád, keby ste si nastavili IDE na normu C99 a aby ste písali čo najlepší kód, nastavili si compilátor tak, že každý warning sa zmení na chybu a compilátor vám nedovolí program scompilovať, kým to nenapravíte.

V Code:Blocks sa to nastavuje takto: Settings -> Compiler and debugger... -> Other options a tam do okna vložíte: -std=gnu99 -Werror -Wall -lm

nastavenie compileru Code Blocks - Práce se soubory v jazyce C

V dnešnom článku si povieme prečo a v ktorých prípadoch je výhodné používať na ukladanie dát textové súbory a kedy binárne súbory.

Textové a binárne súbory

Textové súbory majú výhodu, že je možné kedykoľvek si prehliadnuť ich obsah, vytvoriť ich alebo upraviť bežným editorom. To je aj dôvod, prečo sú vhodné na ukladanie textu.
Na ukladanie iných dátových typov sa síce môžu použiť, ale nie je to výhodné, pretože napríklad číslo 65535 zaberie v textovom súbore priestor 5 Byte a v binárnom len 2 Byte.
Ďalej nie sú vhodné na ukladanie polí, pretože medzi jednotlivé prvky poľa ešte musíme vložiť nejaký separátor, napriklad medzeru a tým je súbor automaticky väčší.

Binárne súbory majú nevýhodu, že síce si ich obsah môžme prehliadnuť napríklad PSPad editorom, ale niečo v nich meniť je prinajmenšom nevhodné, pretože môžeme viac pokaziť ako napraviť.
Výhodou je, že sú väčšinou menšie, rýchlejšie sa s nimi pracuje a pri ukladaní polí nepotrebujú separátor.

Teraz si dokážeme to, čo som napísal.

Program

Napíšeme si jednoduchý program, ktorý najprv vytvorí pole 50 000 000 integerov. Potom to pole načíta do textového súboru a nakoniec ho načíta do binárneho súboru. Každému úkonu sa bude merať čas a nakoniec sa výsledky vypíšu.

Založme si nový Project Console application napríklad UlozenieTextBin. Pridajme si do projektu dva súbory, (source) fce.c a (header) fce.h. Súbor main.c sa vytvorí automaticky.

Najprv si v súbore fce.h zadeklarujeme potrebné funkcie 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 súbore fce.c deklarované 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;
}

Keď 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

velkosť txt súboru - Práce se soubory v jazyce C

test.dat

velkosť binárného súboru - Práce se soubory v jazyce C

Aj veľkosť súborov je veľmi rozdielna.

Doplníme náš program o načítanie textového a binárneho súboru do polí, samozrejme s meraním času.

Do súboru fce.h doplníme deklarácie 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 súbore 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 súboru 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 poľa a jeho zápis do súborov (súbory by sa prepísali), zakomentujeme prvú časť v súbore main.c. Teda všetko čo je nad riadkom
int *pole2;
Scompilujeme a môžme 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 čítania jednotlivých súborov.
To je pre dnešok všetko.

Projekt je napísaný v Code:Blocks na Ubuntu 10.04. Nedá sa otvoriť v Code:Blocks vo Windowse, ale jednotlivé súbory sa môžu skopírovať a bude to pracovať aj tam. Projekt je priložený.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 116x (12.09 kB)
Aplikace je včetně zdrojových kódů v jazyce C

 

Předchozí článek
Manipulace se soubory a práce s errory v jazyce C
Všechny články v sekci
Práce se soubory v jazyce C
Článek pro vás napsal Libor Šimo (libcosenior)
Avatar
Uživatelské hodnocení:
9 hlasů
Obľúbil som si jazyk C a snažím sa ho spoznať čo najhlbšie. Začal som používať c# WPF, je to krása.
Aktivity