Technika manipulace se soubory na nejnižší úrovni

 

 

Soubor

je obecně posloupnost bytů, která je uložena v paměti počítače nebo je přístupná z některého komunikačního portu počítače. Z obecného pohledu byl odvozen pojem soubor na nejnižší úrovni. Tak se lze jednotě dívat na soubor libovolné struktury, libovolného obsahu a původu.

Soubor na nejnižší úrovni je možné vytvořit, zapisovat do něj a modifikovat jeho obsah, otevřít ho, číst v něm, vyhledávat v něm určitý detail. Zkrátka - manipulovat s nim.

Manipulace se soubory se programuje pomocí funkcí (stejně jako v jazyku C), které ve FoxPro2 začínají písmenem F. Jméno souboru se ve funkcích uvádí pouze při jeho vytváření nebo otevírání. Jinak se funkce odkazují na manipulační číslo (někdy se říká "číslo handle"), přidělované automaticky souboru (při jeho vytvoření nebo otevření). Proto otevírání a vytváření musí být programováno jako přiřazovaní příkaz. Jméno souboru nutno zapisovat jako výraz (v uvozovkách). Současně lze uvést cestu k adresáři souboru. Jméno portu se uvádí "COM1" nebo "COM2".

 

 

Vytvoření a otevření souboru

Vytvoření souboru se programuje funkcí FCREATE (soubor nelze vytvořit na komunikačním portu).

Otevření souboru se programuje funkcí FOPEN (soubor musí existovat).

Obě funkce vrací manipulační číslo (handle), které automaticky přiřadí souboru. Při neúspěchu však vrací -1.

 

FCREATE(<expC> [, <expN>])

 

<expC> je jméno vytvářeného souboru,

<expN> je číslo atributu (vlastnosti) souboru. Když není uvedeno, dosadí se standardní hodnota 0.

 

  <expN>        atribut                   význam            
 -------------------------------------------------------------
    0     │ Read, Writte           povoleno čtení a zápis    
    1     │ Read Only              povoleno jen čtení        
    2     │ Hidden                 schovaný soubor           
    3     │ Read Only, Hidden      schovaný, jen čtení       
    4     │ System                 systémový                 
    5     │ System, Read Only      systémový, jen čtení      
    6     │ System, Hidden         syst., schovaný           
    7     │ Syst.,Hidd.,Read Only│  syst.,schov.,jen čtení    

 

Po úspěšném založení souboru zůstává tento otevřen. Existoval-li soubor stejného jména, pak byl přepsán.

 

handle = FCREATE("soubor.txt")

 

FOPEN(<expC> [, <expN>])

 

<expC> je jméno souboru nebo komunikačního portu.

<expN> je číslo použití souboru. Když není uvedeno, dosadí se standardní hodnota 0.

 

   <expN>         použití                    buffer             
 -------------------------------------------------------------
    0       jen pro čtení       │ s vyrovnávací     pamětí   
    1       jen pro zápis       │ s vyrovnávací     pamětí   
    2       pro čtení i zápis   │ s vyrovnávací     pamětí   
   10       jen pro čtení       │ bez s vyrovnávací paměti   
   11       jen pro zápis       │ bez s vyrovnávací paměti   
   12       pro čtení i zápis   │ bez s vyrovnávací paměti   

 

S vyrovnávací pamětí je zpracování souboru rychlejší než bez ní. Vyrovnávací paměti nelze použít u komunikačních portů (nelze číst "do foroty", nutno se přizpůsobit portu).

 

handle = FOPEN("vystup.txt",2)

 

Sdílení souborů na nejnižší úrovni

Soubory na nejnižší úrovni mohou být přístupné více uživatelům současně pouze když byly otevřeny jen pro čtení. V opačném případě jsou soubory otevřené exklusivně. otevřeny jen pro čtení.

 

 

Ukazatel souboru

Ukazatelem souboru na nejnižší úrovni je automatický čítač bytů, který ukazuje po funkcích FOPEN() a FCREATE() na první byte souboru. Ukazatel se automaticky přesouvá na další byty souboru funkcemi FGETS(), FPUTS(), FREAD(), FWRITTE(). Funkce FSEEK() dovoluje nastavit ukazatel podle přání programátora.

Komunikační port nemá ukazatele. Data jsou sekvenčně z portu čtena nebo na port zapisována.

 

Zápis do souboru nebo na port

Zápis do souboru nebo na port lze programovat funkcemi FWRITTE() nebo FPUTS() (soubory musí být otevřeny pro zápis). Obě funkce zapisují řetězec znaků (bytů) s tím rozdílem, že funkce FPUTS() na konci zápisu přidá dva znaky CHR(13)+CHR(10) - CR (carriage return = návrat vozíku) a LF (line feed = posun o řádek). Zatím co FPUTS() se hodí pro vytváření klasických textových souborů, jako je známe například z PASCALu, funkce FWRITTE() má obecnější použití. Funkce mají tvar:

 

FWRITTE(<expN1>, <expC> [, <expN2>])

 

FPUTS (<expN1>, <expC> [, <expN2>])

 

<expN1> je manipulační číslo souboru,

<expC> je řetězec znaků (obecně bytů)

<expN2> je počet znaků z řetězce <expC>, které mají být zapsány

Aby byly zapsané všechny znaky <expC>, musí být <expN2> větší nebo alespoň stejně velké číslo jako je délka řetězce <expC>.

 

Čtení ze souboru nebo z portu

Čtení ze souboru nebo z portu lze programovat funkcemi FREAD() nebo FGETS() (soubory musí být otevřeny pro čtení). Obě funkce čtou řetězec znaků (bytů) předepsané délky, s tím rozdílem, že funkce FPUTS() může ukončit čtení dříve, v okamžiku kdy přečte znaky CR a LF, které nepředá (ignoruje je). Zatím co FGETS() se hodí pro čtení klasických textových souborů, funkce FWRITTE() má obecnější použití. Funkce mají tvar:

 

FREAD(<expN1>, <expC> [, <expN2>])

 

FGETS(<expN1>, <expC> [, <expN2>])

 

<expN1> je manipulační číslo souboru nebo portu,

<expN2> je počet bytů, které mají být funkcí přečteny.

Při neuvedení čte funkce FGETS() až do konce záznamu, maximálně však 254 bytů. Čtení začíná od aktuální pozice ukazatele v souboru. Čtení se ukončí přečtením CR nebo načtením počtu bytů podle <expN2> (situace, která nastane dříve).

 

nacteny_radek_textu = FGETS(handle)

 

Aby byly zapsané všechny znaky <expC>, musí být <expN2> větší nebo alespoň stejně velké číslo jako je délka řetězce <expC>.

 

 

Změna velikosti souboru

Změna velikosti souboru se programuje pomocí funkce:

 

FCHSIZE(<expN1>, <expN2>)

 

<expN1> je manipulační číslo souboru, který musí být otevřen pro zápis,

<expN2> je požadovaná nová velikost souboru v počtu bytů.

Funkce vrací číselnou hodnotu konečné velikosti souboru v bytech, -1 při neúspěchu.

 

= FCHSIZE(soubor, 0) && zkrácení souboru na nulovou délku

 

 

Test úspěšnosti práce se souborem

Úspěšnost použití manipulačních funkcí je vhodné testovat pomocí funkce

 

FERROR()

 

která vrací nulu, když předcházející funkce skončila bez chyby nebo číslo chyby při neúspěchu předcházející akce.

 

  číslo chyby           důvod                                      
 -----------------------------------------------------------------
       2         Nenašel se soubor                               
       4         Otevřeno příliš mnoho souborů                   
       5         Soubor je nepřístupný                           
       6         Použito neplatné manipulační číslo              
       8         Překročen rozsah paměti                         
      25         Chyba v hledání, nemůže hledat před souborem    
      29         Disk je zaplněn                                 
      31         Blíže nespecifikovaná chyba, dosaženo EOF, atd.│ 

 

 

Zápis souboru na disk

Když je otevřen soubor s vyrovnávací pamětí (buffer), pak informace zapisovaná do souboru se nezapisuje na disk ale do operační paměti počítače. V optimální periodicitě je vhodné programovat zápis obsahu vyrovnávací paměti na disk a tak zamezit ztrátě informací v případě technické závady. K tomu se používá funkce:

 

FFLUSH(<expN>)

 

<expN> je manipulační číslo souboru. Funkce signalizuje úspěšné provedení hodnotou .T.

 

= FFLUSH(handl)

 

Hledání v souboru

Hledání v souboru se programuje pomocí funkce FSEEK(), která posouvá ukazatel v souboru a pomocí funkce FREAD(), která provádí potřebnou extrakci podřetězců. Funkce má tvar:

 

FSEEK(<expN1>, <expN2> [, <expN3>])

 

<expN1> je manipulační číslo souboru,

<expN2> je posunutí ukazatele v počtu bytů (+ vpřed,- vzad)

<expN3> = 0 (standard) posun vzhledem k počátku,

<expN3> = 1 posun vzhledem k aktuální pozici ukazatele,

<expN3> = 2 posun vzhledem ke konci souboru.

 

= FSEEK(handl, 128, 1)

 

 

Test konce souboru

K testování, zda ukazatel dosáhl konce souboru se používá funkce:

 

FEOF(<expN>)

 

kde <expN> je manipulační číslo. Funkce vrací .T., když je ukazatel na konci souboru.

 

IF FEOF(handl)

 

 

Uzavření souboru nebo portu

Soubory na nejnižší úrovni, které byly otevřeny funkcemi FCREATE() nebo FOPEN(), nutno po ukončení práce uzavřít funkcí:

 

FCLOSE(<expN>)

 

kde <expN> je manipulační číslo. Úspěšné uzavření je signalizováno vrácenou hodnotou .T.

 

= FCLOSE(handle)

 

 

Specifika komunikačních portů

Komunikační porty umožňují styk počítače uživatele s modemem nebo vnějšími zařízeními (včetně zařízení laboratorního typu). Komunikační porty (COM1, COM2, apod.) mohou být zpřístupněny právě pomocí souborů na nejnižší úrovni. Před zahájením komunikace s portem musí být tento inicializován příkazem operačního systému DOS MODE, který specifikuje parametry portu (přenosovou rychlost, datové bity, stop bity a opakování).

 

Cvičení

Navázání spojení

Nejzajímavější z tématu o použití portu je navázání spojení počítačů pomocí telefonní linky, které vysvětluje následující příklad (Použité příkazy a inicializační řetězce se týkají standardního modemu. U jiných typů mohou být drobné odlišnosti.)

 

telefonni_cislo="458215"                             && Zde by měla být programována volba čísla

RUN mode com1:1200,N,8,1,p                && Inicializace portu COM2

modem=FOPEN("com1", 12)                              && Pokus o otevření portu

IF ERROR() <> 0                                       && Test úspěšnosti

WAIT " Nelze navázat spojení ";

+"...lib.klíč..." WINDOW            && Neúspěch !

RETURN                                           && Konec úlohy

ENDIF

 =FPUTS(modem, "ATDT"+telefonni_cislo)                  && Volba stanice

 

******                                                            && Zde bude zřejmě zpracování

 

WAIT 'Ukončení spojení ...lib.klíč...' WINDOW            && Konec úlohy

=FPUTS(modem, 'ATZH')                                        && Ukončení spojení

=FCLOSE(modem)                                        && Uzavření komunikace s modemem

 

 

Podmíněné vytvoření souboru

Problém podmíněného vytvoření souboru spočívá v tom, že soubor se vytváří pouze v případě, že neexistuje. V opačném případě se soubor pouze otevře.

 

nazev="Podmíněné vytvoření souboru"            && Název úlohy

IF FILE("zapis.txt")                                           && Test existence souboru funkcí FILE(),

zapis=FOPEN("zapis.txt",12)                    && když existuje, pak pouze otevření

ELSE

zapis=FCREATE("zapis.txt")                      && když neexistuje, pak vytvoření

ENDIF

IF  zapis < 0

WAIT "Soubor ZAPIS.TXT nelze otevřít "+;

"ani vytvořit "WINDOW NOWAIT

RETURN

ELSE

WAIT "Soubor ZAPIS.TXT byl otevřen";

WINDOW NOWAIT

ENDIF

=FPUTS(zapis,"Zde je možné  zapisovat:")

=FPUTS(zapis," ")

MODIFY FILE zapis.txt

=FCLOSE(zapis)

 

 

Technické podmínky vytvoření souboru

Vytvoření souboru závisí na řadě podmínek, které je nutno testovat a podat o nich zprávu programu, v některých případech i uživateli. Rozhodující podmínky a jejich ošetření jsou uvedeny ve funkci VYTVOR následujícího příkladu.

Pozor! Funkce pracuje spolehlivě pro všechna zařízení, kromě disket (těžko soudit, zda jde o nedostatek DOS nebo FoxPro). Pro testování disket nutno požít program uvedený v kapitole pojednávající o binárních modulech.

 

CLEAR                                                           && Výmaz obrazovky

nazev="Funkce pro vytvoření souboru"            && Název příkladu

@12,12 SAY nazev                                      && Zobrazení názvu příkladu

@11,10 TO 13,LEN(nazev)+3+10 DOUBLE            && Rámeček kolem názvu

soubor="POKUS.TMP"                                && Název pokusného souboru

kanal=vytvor(soubor)                                               && Použití funkce VYTVOR()

=FCLOSE(kanal)                                         && Uzavření pokusného souboru

DELETE FILE &soubor                                    && Zrušení pokusného souboru

WAIT "soubor "+soubor+" zrušen" WINDOW NOWAIT            && Informace o zrušení souboru

 

FUNCTION vytvor                                     && Definování funkce VYTVOR

PARAMETERS ss                                          && Formální parametr se jménem souboru,

s=FCREATE(ss)                                           &&  který má být vytvořen

DO CASE                                           && V s je po úspěch manipulační číslo souboru

CASE s>1                             && Testování se provádí podle hodnoty vrácené funkcí

"Soubor "+ss;               &&  FERROR()

+" úspěšně vytvořen, handle="+STR(s,2)

&& Funkce vrací manipulační číslo,

CASE FERROR()=4              &&  v případě úspěchu

t="Otevřeno příliš mnoho souborů"            &&  nebo -1, v případě neúspěchu

CASE FERROR()=5

"Znemožněn přístup"                      && Neexistují zařízení nebo adresář

CASE FERROR()=8

"Překročen rozsah paměti"

CASE FERROR()=29

"Disk je přeplněný"

CASE FERROR()=31

t="Blíže neurčená chyba"            && Technická závada

ENDCASE

WAIT t+"...lib.klíč..." WINDOW                 && Ohlas uživateli

RETURN s                                                      && Vrácení manipulačního čísla

Technické podmínky vytvoření souboru

Před kopírováním souboru (jakéhokoliv typu) nutno předen zjistit jeho velikost, kterou pak následně nutno porovnat s hodnotou funkce DISKSPACE(). Programování zjištění velikosti je uvedeno ve funkci VELIKOST() následujícího příkladu.

 

CLEAR                                                           && Výmaz obrazovky

nazev="Test velikosti souboru"                     && Název úlohy

@12,12 SAY nazev                                      && Zobrazení názvu úlohy

@11,10 TO 13,LEN(nazev)+3+10 DOUBLE            && Rámeček

soubor="cesty.dbf"                                                   && Volba vstupního souboru

ve=velikost(soubor)                                       && Použití funkce kontrolující velikost souboru

 

FUNCTION  velikost                                               && Definice funkce

PARAMETERS ss                                          && Formální parametr s názvem souboru

IF !FILE(ss)                                                    && Test existence vstupního souboru

t="Soubor "+ss+" neexistuje"            && (v příkladu byl použit databázový soubor)

velikost = -1                          && Neúspěch je signalizován zápornou hodnotou

ELSE

H=FOPEN(ss,2)                               && Otevření testovaného souboru

velikost=FSEEK(H,0,2)                    && Zjištění počtu bytů od polohy ukazatele

t="Velikost souboru "+ss+" je ";            &&  po konec souboru

ALLTRIM(STR(velikost,5))+" bytů "

WAIT t+"...lib.klíč..."  WINDOW

=FCLOSE(H)

RETURN velikost

 

 

Použití příkazů pro zápis

Rozdíl práce funkcí FWRITTE() a FPUTS() je demonstrován ve funkci VYPIS(), která zapíše název a obsah položky libovolného databázového souboru do zvoleného souboru na nejnižší úrovni.

 

CLOSE ALL                                                               && Uzavření všech souborů

CLEAR                                                                       && Výmaz obrazovky

nazev="Zápis vybraných položek"                                 && Název úlohy

@12,12 SAY nazev                                                  && Zobrazení názvu

@11,10 TO 13,LEN(nazev)+3+10 DOUBLE            && Rámeček

SET PROCEDURE TO pr222_3            && Informace pro překladač, kde hledat nedefinované

soubor="POKUS.TMP"                    &&  funkce

kanal=vytvor(soubor)                                   && Použita funkce definovaná v předchozím příkladě

SELECT 0                                          && Volba první volné pracovní oblasti

USE cesty AGAIN                                    && Otevření zkušebního souboru

FOR zaznam=1 TO RECCOUNT()            && Dáme vypsat všechny položky všech záznamů

FOR polozka=1 TO FCOUNT()

&& Funkce FCOUNT() vrací počet položek záznamu

=vypis(zaznam,polozka,kanal)            && Volání funkce VYPIS()

ENDFOR

ENDFOR

USE

=FCLOSE(kanal)                             && Uzavření souboru na nejnižší úrovni

@24,1 SAY "Konec klávesami CTRL+ENTER"

&& Návod na ukončení prohlížení nebo editace výstupu

MODIFY FILE (soubor)                      && Umožnění přístupu uživatele k výpisu

CLOSE ALL                                       && Uzavření všech souborů

DELETE FILE &soubor                        && Zrušení výpisu

CLEAR                                               && Výmaz obrazovky

 

FUNCTION vypis                           && Definice funkce s parametry:

PARAMETERS zaznam,polozka,H                  && číslo záznamu, pořadí položky,

 

*obě hodnoty se zadávají pořadovým číslem    && manipulační číslo

 

aa=RECNO()                                     && Nutno zachovat původní polohu ukazatele vstupu

GO zaznam                                         && Vyhledání vypisovaného záznamu

=FWRITE (H,STR(zaznam,4)+" ")            && Výpis čísla záznamu

=FWRITE(H,FIELD(polozka)+' = ')                      && Výpis jména položky na stejný řádek

A=FIELD(polozka)                           && Pomocný zápis jména položky

=FPUTS (H,&a)                        && Výpis obsahu položky na stejný řádek,

GO aa                                                 &&   současně připraven zápis na nový řádek