4. díl - Přesun v souboru a implementace v operačním systému

C++ Práce se soubory Přesun v souboru a implementace v operačním systému

V minulém díle jsme si řekli, jak lze pracovat s binárními soubory. Jak je lze číst a jak do nich zapisovat. Uvedené postupy byly pouze lineární, to znamená, že jsme soubor buď četli (nebo do něj zapisovali) od začátku po konec souboru. Ne vždy nám tento přístup vyhovuje. Na začátku souboru můžeme mít vytvořenou tabulku, která nám řekne, kde jsou jaké informace zapsány. Chceme-li přečíst pouze jednu informaci, je zbytečné kvůli tomu načíst celý soubor. V takových situacích by nám vyhovovalo přesunout se přímo na požadované místo v souboru a číst od tohoto místa.

Změna pozice v souboru

Ke změně pozice v souboru použijeme funkci fseek. Funkce má tři parametry:

  • Ukazatel na FILE, který jsme získali z funkce fopen.
  • Počet bajtů, o které se chceme v souboru posunout. V závislosti na třetím parametru se také může jednat o bajt, na který se chceme přesunout.
  • Třetí parametr řídí pozici, ze které se v souboru přesouváme. Konstanta SEEK_SET udává začátek souboru, konstanta SEEK_CUR udává z aktuálního místa. Některé kompilery podporují ještě konstanty SEEK_END, která udává konec souboru, nicméně není obsažena ve standardu a tak nemusí být dostupná na všech platformách.

Návratovou hodnotou funkce je standardně 0. Vyskytl-li se nějaký problém, funkce vrací nenulovou hodnotu. Změna pozice v konzoli by nedávala smysl, a proto funkce nefunguje pro konstanty stdin a stdout, které jsme si ukázali v minulém díle.

Pro ukázku si napíšeme funkci, která přijímá ukazatel na soubor a číslo určující nový offset. Nejprve ze souboru přečte dvě čísla (první udává současný offset, druhé potom délku dat). Funkce bude mít za úkol tyto data přenést na nový offset, určený druhým parametrem.

int presun_v_souboru(FILE* soubor, int novy_offset)
{
    int stara_pozice_dat;
    int delka_dat;
    void* data;

    fseek(soubor, 0, SEEK_SET); //přesuneme se na začátek souboru
    fread(&stara_pozice_dat, sizeof (int), 1, soubor); //přečteme staré umístění dat
    fread(&delka_dat, sizeof (int), 1, soubor); //přečteme délku dat
    data = malloc(delka_dat); //alokujeme pro data dostatek prostoru
    fseek(soubor, stara_pozice_dat - 2 * sizeof (int), SEEK_CUR); //přesuneme se na místo, kde jsou data uložena
    fread(data, 1, delka_dat, soubor); //přečteme data
    fseek(soubor, novy_offset, SEEK_SET); //přesuneme se na nové místo, kam mají být data uložena
    fwrite(data, 1, delka_dat, soubor); //zapúíšeme na toto místo data
    free(data); //uvolníme mezipaměť, kterou jsme používali
    fseek(soubor, 0, SEEK_SET); //přesuneme se zpět na začátek souboru
    fwrite(&novy_offset, sizeof (int), 1, soubor); //přepíšeme původní offset na nový
    return 0;
}

Pro jednoduchost jsem vynechal kontrolu, zda operace byla provedena úspěšně. Každé volání funkce by mělo být spojeno s podmínkou, zad funkce nevrátila nenulovou hodnotu. V takovém případě došlo k problémům se souborem a program by měl chybu opravit.

Další funkce pracující s pozicí

Standardní knihovna poskytuje i další funkce, které pracují s pozicí v souboru. Jedna z nich je ftell, která vrací aktuální pozici v souboru. Jediný parametr, který potřebuje, je ukazatel na FILE. Poslední funkcí je rewind. Stejně jako ftell přijímá pouze ukazatel na FILE, ale změní pozici na začátek souboru. Tím je funkce ekvivalentní s fseek, ale je přeci jen rychlejší psát jeden parametr než tři.

Vyrovnávací paměť

Harddisk počítače je oproti zbytku paměťových prostor, které má počítač k dispozici, nejpomalejší médium. Čas přístupu do RAM se měří v nanosekundách, zatímco čas přístupu na harddisk se měří v milisekundách (mili -> mikro -> nano). Bylo by tedy nepraktické každý zapsaný bajt odesílat na harddisk. Program by se celý zpomalil jenom protože by čekal, až se jeden bajt zapíše na harddisk. Proto operační systém má vyrovnávací paměť. Při čtení souboru se z harddisku nenačte pouze první bajt, ale větší část. Tato část se uloží do vyrovnávací paměti, takže až bude chtít program data na dalším bajtu, má je operační systém již v paměti a nemusí se znovu připojovat na harddisk. Obdobným způsobem funguje i zápis. Operační systém si nejdříve data ukládá v mezipaměti. Až je dat dostatečné množství, tak je všechny pošle harddisku, ať je uloží. Opět se tím snižují čas, kdy by program musel čekat, až se změny do souboru zapíší.

fflush

Chování mezipaměti můžeme do jisté míry ovlivnit funkcí fflush. Ta vyprázdní mezipaměť a všechny změny zapíše do souboru. Jediný parametrem je ukazatel na FILE. Tato funkce je volána automaticky při fclose nebo při ukončení programu.

Změna módu otevřeného souboru

Změna módu otevřeného souboru sebou nese několik akcí. Nejprve je potřeba uložit si aktuální pozici v souboru. Poté je potřeba soubor zavřít otevřít s novým módem a přesunout se na původní místo. Určitě by nebylo problém takovou funkci napsat, ale standard nám poskytuje vlastní funkci - freopen. Funkce má tři parametry:

  • Řetězec udávající jméno souboru.
  • Nový mód, pod kterým se má soubor otevřít.
  • Ukazatel na FILE*, který se upravuje.

Návratová hodnota je buď původní (třetí) parametr, nebo NULL při neúspěchu. Funkce lze použít ke dvěma účelům. Pokud namísto prvního parametru použijeme NULL, funkce se pokusí změnit přístupová práva otevřeného souboru. Pokud uvedeme název souboru, funkce neotevře znovu ten stejný soubor, ale otevře nový (určený jménem) a požadovaným módem. V jistém smyslu tedy můžeme o funkci přemýšlet jako o funkci, která dokáže výstup i přesměrovat. Na rozdíl od fseek, lze freopen použít i pro standardní vstup a výstup. Můžeme tedy jednoduše přesměrovat výstup tak, aby nešel do konzole, ale do souboru. To ukazuje následující kód:

#include <stdio.h>

int main ()
{
  freopen ("soubor.txt","w",stdout);
  printf ("Tato veta se ulozi do souboru");
  fclose (stdout);
  return 0;
}

To bude pro tento díl vše. Příště bude již poslední díl na soubory a podíváme na se manipulaci se soubory na disku a na práci s errory, které se mohou při běhu programu vyskytnout.


 

Stáhnout

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

 

  Aktivity (2)

Článek pro vás napsal patrik.valkovic
Avatar
Věnuji se programování v C++ a C#. Kromě toho také programuji v PHP (Nette) a JavaScriptu.

Jak se ti líbí článek?
Ještě nikdo nehodnotil, buď první!


 


Miniatura
Všechny články v sekci
Práce se soubory v jazyce C
Miniatura
Následující článek
Manipulace se soubory a práce s errory

 

 

Komentáře

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.

Zatím nikdo nevložil komentář - buď první!