7. Typ soubor Souborem dat běžně rozumíme uspořádanou množinu dat, uloženou mimo operační paměť počítače (na disku). Pascalský soubor je abstrakcí skutečného souboru, program neobsahuje žádné informace o fyzických vlastnostech souborů. Na soubor se v pascalu odkazujeme pomocí proměnné typu file. Soubor chápeme jako posloupnost složek stejného typu, pro níž jsou definovány různé operace. Tyto operace umožňují sekvenční zpracování souboru, tj. postupné vytváření nebo čtení souboru. Při tomto druhu zpracování je v každém okamžiku přístupná jediná položka souboru, položky se zpracovávají v pořadí, jak byly uloženy.
Jsou tři třídy pascalských souborů: - typové, - textové, - netypové. Typové soubory nejsou přímo čitelné, slouží pro ukládání dat, pro komunikaci mezi dvěma programy a pod. Textové soubory slouží pro komunikaci mezi programem a uživatelem, uživatel je může přímo číst (např. příkazem type nebo v libovolném textovém editoru). Netypové soubory jsou tzv. nízkoúrovňové. Jsou používány pro přímý zápis (čtení) datových bloků na disk. Lze je použít v situaci, kdy soubor má nějakou vnitřní strukturu, určenou aplikací, např. obrázky. Popis typu soubor
Příklady deklarace typu soubor: type soubor_cisel = file of real; radek = array[1..80] of char; soubor_radku = file of radek; pole_souboru = array[1..3] of soubor_cisel; var f : soubor_cisel; Dříve než proměnnou typu soubor začneme používa, musíme ji spojit s vnějším souborem pomocí procedury assign: assign(f,'data.dat'); Vnějším souborem může být diskový soubor, klávesnice nebo monitor.
Dále musí být soubor otevřen. Existující soubor může být otevřen procedurou reset: reset(f); Nový soubor se vytváří a otevírá procedurou rewrite: rewrite(f); Chceme-li přidat data na konec existujícího souboru, otevřeme ho příkazem append: append(f); Textové soubory otevřené příkazem reset jsou přístupné pouze pro čtení, otevřené rewrite nebo append pouze pro zápis. Typové soubory otevřené příkazem reset je možno číst i zapisovat.
Počet současně otevřených souborů je operačním systémem omezen. Soubory otevřené pro zápis musí být na závěr programu uzavřeny příkazem close: close(f); Příkaz close provede vyprázdnění komunikačního bufferu. Buffer se používá k dočasnému uložení zapisovaných dat, aby přenos na disk probíhal po větších celcích. Pokud k uzavření souboru nedojde, může být jeho část uložená v bufferu ztracena.
Př.: Program pro překopírování znakového souboru s vynecháním prazdných řádků. program kopie; const pocet_sloupcu=80; pocet_sloupcu=80;type radek = array[1..pocet_sloupcu] of char; radek = array[1..pocet_sloupcu] of char; soubor_radku = file of radek; soubor_radku = file of radek;var prazdny, pom_radek : radek; prazdny, pom_radek : radek; sloupec : 1..pocet_sloupcu; sloupec : 1..pocet_sloupcu; vstup, vystup : soubor_radku; vstup, vystup : soubor_radku;begin assign(vstup,'vstup.txt'); reset(vstup); assign(vstup,'vstup.txt'); reset(vstup); assign(vystup,'vystup.txt'); rewrite(vystup); assign(vystup,'vystup.txt'); rewrite(vystup); for sloupec := 1 to pocet_sloupcu do prazdny[sloupec] := ' '; for sloupec := 1 to pocet_sloupcu do prazdny[sloupec] := ' '; while not eof(vstup) do begin while not eof(vstup) do begin read(vstup, pom_radek); read(vstup, pom_radek); if pom_radek <> prazdny then write(vystup,pom_radek); if pom_radek <> prazdny then write(vystup,pom_radek); end; end; close('vystup'); close('vystup');end.
Soubor je chápán jako posloupnost složek stejného typu. Každá složka má své pořadové číslo charakterizující polohu v souboru. První složka je označena číslem 0. Soubory jsou obvykle přístupné sekvenčně, složky jsou čteny standardní procedurou read(f) nebo zapisovány standardní procedurou write(f). Ukazatel pozice v souboru se po každé takové operaci automaticky nastavuje na následující hodnotu. K určení aktuální pozice v souboru slouží standardní funkce filepos. Aktuální velikost souboru zjistí funkce filesize.
Typové soubory je možno spracovávat s přímým přístupem. Při tomto druhu zpracování je možno přesunout ukazovátko aktuální pozice v souboru na libovolný záznam. Záznam se přečte příkazem read nebo přepíše příkazem write. Jestliže ukazovátko ukazuje za poslední položku, příkaz write přidá novou položku na konec souboru. Přesun ukazovátka se provádí příkazem seek: seek(f,n); n je typu longint.
Textové soubory Typ text má všechny vlastnosti souboru typu file of char a navíc jsou pro něj definovány některé další operace, které respektují členění souboru na řádky. Oddělovače řádků nejsou definovány normou jazyka, norma oddělovač chápe jako jeden znak. V TP tvoří oddělovač dva znaky CR, LF s kódy 13,10. Deklarace proměnné typu textovy soubor: var f : text; f : text; Oddělovač řádků se zapíše příkazem writeln(f). Přeskočení zbývajících znaků na řádku příkazem readln(f). Test konce řádku a konce souboru - eoln(f), eof(f).
Př.: Program pro překopírování textového souboru. program kopie; var vstup,vystup : text; vstup,vystup : text; x : char; x : char;begin assign(vstup,'vstup.txt'); reset(vstup); assign(vstup,'vstup.txt'); reset(vstup); assign(vystup,'vystup.txt'); rewrite(vystup); assign(vystup,'vystup.txt'); rewrite(vystup); while not eof(vstup) do begin while not eof(vstup) do begin while not eoln(vstup) do begin while not eoln(vstup) do begin read(vstup,x); write(vystup,x); read(vstup,x); write(vystup,x); end; end; writeln(vystup; writeln(vystup; readln(vstup); readln(vstup); end; end; close(vystup); close(vystup);end.
V souborech typu text je možno číst a zapisovat jiný typ než char - integer, real, string a zapisovat boolean. Standardní textový vstup a výstup je možno přesměrovat do souboru: standardně: assign(input,''); reset(input); assign(output,''); rewrite(output); přesměrování: assign(input,'data.dat'); reset(input); assign(output,'data.vys'); rewrite(output); Př. Zpracování textového souboru - zjištění počtu znaků, slov a řádků.
program text(input,output); var veslove : boolean; veslove : boolean; zn : char; zn : char; pz,ps,pr : integer; pz,ps,pr : integer;begin veslove := false; veslove := false; pz := 0; ps := 0; pr := 0; pz := 0; ps := 0; pr := 0; while not eof do begin while not eof do begin while not eoln do begin while not eoln do begin read(zn); read(zn); pz := pz + 1; pz := pz + 1; if zn = ' ' then veslove := false if zn = ' ' then veslove := false else else if not veslove then begin if not veslove then begin veslove := true; ps := ps + 1; veslove := true; ps := ps + 1; end; end; readln; readln; veslove := false; pr := pr + 1; veslove := false; pr := pr + 1; end; end; writeln('pocet znaku = ',pz,' pocet slov = ',ps,' pocet radku = ',pr); writeln('pocet znaku = ',pz,' pocet slov = ',ps,' pocet radku = ',pr);end.