NOVINKA - Online rekvalifikační kurz Python programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
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í.

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

Zpět

Upozorňujeme, že diskuze pod našimi online kurzy jsou nemoderované a primárně slouží k získávání zpětné vazby pro budoucí vylepšení kurzů. Pro studenty našich rekvalifikačních kurzů nabízíme možnost přímého kontaktu s lektory a studijním referentem pro osobní konzultace a podporu v rámci jejich studia. Toto je exkluzivní služba, která zajišťuje kvalitní a cílenou pomoc v případě jakýchkoli dotazů nebo projektů.

Komentáře
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.

Odpovědět
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ší
Editováno 8.6.2014 20:10
 
Odpovědět
8.6.2014 20:09
Avatar
Odpovídá 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ú).

Odpovědět
9.6.2014 9:19
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
coells
Tvůrce
Avatar
Odpovídá 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...
 
Odpovědět
9.6.2014 11:02
Avatar
Odpovídá 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)

Editováno 9.6.2014 12:40
Odpovědět
9.6.2014 12:38
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
coells
Tvůrce
Avatar
Odpovídá 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.

 
Odpovědět
9.6.2014 13:00
Avatar
Odpovídá 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.

Odpovědět
9.6.2014 13:12
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
coells
Tvůrce
Avatar
Odpovídá 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š.

Editováno 9.6.2014 14:03
 
Odpovědět
9.6.2014 14:02
Avatar
Odpovídá 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:

Odpovědět
9.6.2014 17:11
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
coells
Tvůrce
Avatar
Odpovídá 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 :-)

 
Odpovědět
9.6.2014 17:34
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 33.