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