IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

Diskusia – 6. diel - Rozdiel medzi textovými a binárnymi subor v C - dodatok

Späť

Upozorňujeme, že diskusie pod našimi online kurzami sú nemoderované a primárne slúžia na získavanie spätnej väzby pre budúce vylepšenie kurzov. Pre študentov našich rekvalifikačných kurzov ponúkame možnosť priameho kontaktu s lektormi a študijným referentom pre osobné konzultácie a podporu v rámci ich štúdia. Toto je exkluzívna služba, ktorá zaisťuje kvalitnú a cielenú pomoc v prípade akýchkoľvek otázok alebo projektov.

Komentáre
Avatar
David Hartinger
Vlastník
Avatar
David Hartinger:8.6.2014 18:32

Problém binárních souborů je hlavně jejich verzování. Když ukládáš třeba nějaký struct a rozhodneš se, že bude mít jeden parametr navíc, změníš jeho velikost a původně uložená série structů v nějakém souboru již nepůjde načíst. Tento problém může také ovlivnit rozhodnutí zda použít text nebo bin.

Odpovedať
8.6.2014 18:32
New kid back on the block with a R.I.P
Avatar
coells
Tvůrce
Avatar
coells:8.6.2014 20:09

Ahoj Libco,

několik faktických poznámek:

  1. korektní definice funkcí pro práci se soubory by byla následující
void vytvor_txt_subor(const int *data, int size, const char* path);
  • konstatní pointery definují sémantiku funkce, která hodnoty jenom čte, ale nemění je, podívej se na definice fopen(), fwrite(), printf()
  • stejně tak velikost zapisovaných souborů by měla být vstupní parametr, nikoliv makro
  • IMHO, nepoužívej makra, málokdy je k tomu dobrý důvod a - bez urážky - makra jsou spíše pro zkušenější programátory
  1. zápis do textového souboru není pomalejší, rozdíl v časech dostáváš jenom kvůli odlišnému přístupu:
  • u textového souboru nepoužíváš buffer
  • textový soubor zapisuješ přes printf, takže tam máš overhead nejen konverze do stringu, ale také formátování vstupu
  • ve skutečnosti dokážu přepsat tvoji funkci vytvor_txt_subor() tak, že bude stejně rychlá jako funkce, která pracuje s binárním souborem (kromě odlišné velikosti souborů)
  1. &pole[0] je stejné, jako když napíšeš "i + 1 - 1", stačilo by prostě napsat "pole"
  2. chybí mi tam chybová kontrola práce se soubory
  • stáhl jsem si Tvůj příklad a první věc byla, že nefungoval kvůli neexistenci souborů
  1. trochu víc iffů, které kontrolují správný průběh programu by zřejmě neškodilo, hlavně když načítáš soubory do paměti, nechceš zapisovat mimo rozsah pole a stejně tak sem tam něco zkrátit nebo vynechat, abys měl méně kódu - jazyku C to prostě sluší
Editované 8.6.2014 20:10
 
Odpovedať
8.6.2014 20:09
Avatar
Odpovedá na coells
Libor Šimo (libcosenior):9.6.2014 9:19

Ďúfal som, že mi to zhodnotíš. :)

  1. Díky za upresnenie, s const sem ešte nerobil, ale po tvojom upozornení to budem používať.

Makro som použil preto, aby som nemusel opakovane vypisovať počet prvkov poľa, ale máš pravdu, keď sa int size doplní do funkcií, stačí počet prvkov poľa definovať na začiatku funkcie main().

  1. Chcem ťa poprosiť, aby si sem napísal spomínanú funkciu, pretože si ju neviem predstaviť.
  2. Samozrejme, že máš pravdu. Ja som len chcel, aby každý pochopil, že to záčína adresou na prvý prvok poľa.
  3. Chybovú kontrolu som plánoval do ďalšieho článku, v ktorom chcem písať o konkrétnej práci so súbormi.

Za priložený súbor sa ospravedlňujem, nie preto, že tam neexistovali súbory (zbytočne by zabrali veľa miesta), ale preto, že som neodkomentoval prvú časť funkcie main().

  1. Kontrolu načítania a zápisu som plánoval do ďalšieho článku.

V tomto článku mi išlo o poukázanie na rozdiely trvania práce s jednotlivými typmi súborov. Samotný kód je len pomocný.
Dúfam, že mi dokážeš, čo si písal o trvaní práce s textovým súborom a ja to celé prehodnotím.
Vychádzal som z knižky od Herouta (všetci ju odporúčajú).

Odpovedať
9.6.2014 9:19
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
coells
Tvůrce
Avatar
Odpovedá na Libor Šimo (libcosenior)
coells:9.6.2014 11:02

Přepni kompilátor do release módu, a změř si tuhle funkci.
Za alokaci POCET*7 se omlouvám, počítám s čísly v rozsahu 100000-300000. Obvykle by stačil buffer o velikosti 10kB, což vyřeší jeden for-cyklus navíc. Můžeš si to vyzkoušet přepsat ;-)

static
void itoa_ansi(int value, char *dst)
{
    char *tmp = dst;
    char t;

    *tmp = '0';
    while (value > 0)
        *tmp++ = value % 10 + '0', value /= 10;
    *tmp-- = ' ';

    while (tmp > dst)
        t = *tmp, *tmp-- = *dst, *dst++ = t;
}

void vytvor_txt_subor(int pole[], char* subor)
{
    const int n = POCET * 7;
    char *buffer = (char *)malloc(sizeof(char) * n + 1);

    for (int i = 0; i < POCET; i++)
        itoa_ansi(pole[i], buffer + i * 7);

    FILE *fw = fopen(subor, "w");
    fwrite(buffer, sizeof(char), n, fw);
    fclose(fw);

    free(buffer);
}

Výsledek na mém notebooku (binární soubor jsem dal před textový, aby se ho netýkala alokace bufferu). Časy už hodně skáčou kvůli cache, ale když vezmeš v úvahu počet dat, tak je rozdíl prakticky neměřitelný.

Vytvorim pole celych cisiel.
Potrebny cas 0.955 secund.

Zapisem pole do binarneho suboru.
Potrebny cas 3.213 secund.

Zapisem pole do textoveho suboru.
Potrebny cas 2.673 secund.
Pokračujte stisknutím libovolné klávesy...
 
Odpovedať
9.6.2014 11:02
Avatar
Odpovedá na coells
Libor Šimo (libcosenior):9.6.2014 12:38

Pekné.
Prekonvertoval si čísla na reťazce a potom si ich uložil, ale keď ich bude treba načítať, zase to bude treba prekonvertovať na čísla a to zaberie čas.
Ani si nechcem predstaviť načítanie poľa štruktúr z textového súboru.
Navyše na mojom pc v práci (winxp) výstup (release) vyzerá tak, že načítanie textového súboru trvá v priemere skoro 2 krát viac ako binárneho. (spustil som to zhruba 10x)

Editované 9.6.2014 12:40
Odpovedať
9.6.2014 12:38
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
coells
Tvůrce
Avatar
Odpovedá na Libor Šimo (libcosenior)
coells:9.6.2014 13:00

Časy se budou lišit podle překladače, hardwaru a OS. Na OS X mám také úplně jiné výsledky než na Win7. To je faktor, který se špatně ovlivňuje, pokud jsou data takhle velká. Stejně tak clang a MS Visual Studio jsou mnohem lepší než GCC, takže se také projeví rozdíl v rychlosti. V mém případě už byla práce s textem zanedbatelná, protože většinu času zabral zápis na disk.

Smysl je ale v tom, že se nedá říct, že práce s textovými soubory je pomalejší než práce s binárními soubory. Pomalejší je pouze práce s jinou reprezentací dat než je ta nativní. A i tam lze napsat velice efektivní kód, pokud je to potřeba.

 
Odpovedať
9.6.2014 13:00
Avatar
Odpovedá na coells
Libor Šimo (libcosenior):9.6.2014 13:12

Schválne to doma vyskúšam na ubuntu. Tam som mal v pôvodnom znení najväčšie rozdiely, tak som zvedavý.
Ty vlastne používaš na ukladanie funkcie fwrite(), ktorá sa nativne používa pre binárne súbory.

Odpovedať
9.6.2014 13:12
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
coells
Tvůrce
Avatar
Odpovedá na Libor Šimo (libcosenior)
coells:9.6.2014 14:02

fwrite() se nativně používá pro binární i textové soubory. Textový mód pouze značí, že se \n má chovat podle toho, jak to vyžaduje OS. Na windows se bude přepisovat na \r\n, na unixu nemá žádný efekt.

viz http://msdn.microsoft.com/…S.71%29.aspx

V příkladu, který máš v článku, je naprosto jedno, jaký mód použiješ.

Editované 9.6.2014 14:03
 
Odpovedať
9.6.2014 14:02
Avatar
Odpovedá na coells
Libor Šimo (libcosenior):9.6.2014 17:11

Ta som doma a testol som to tvoje na ubuntu 12.04 a gcc.
Výsledok:

Odpovedať
9.6.2014 17:11
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
coells
Tvůrce
Avatar
Odpovedá na Libor Šimo (libcosenior)
coells:9.6.2014 17:34

V tom případě dokážu kód upravit tak, aby s kvalitním překladačem, na dobrém CPU a Win7 běhal stejně rychle :-)

 
Odpovedať
9.6.2014 17:34
Robíme čo je v našich silách, aby bola tunajšia diskusia čo najkvalitnejšia. Preto do nej tiež môžu prispievať len registrovaní členovia. Pre zapojenie sa do diskusie sa zaloguj. Ak ešte nemáš účet, zaregistruj sa, je to zadarmo.

Zatiaľ nikto nevložil komentár - buď prvý!