kategória | ||||||||||
|
||||||||||
|
||
Fájlkezelés, fájlok szerkezete, megnyitása, írása, olvasása, egyéb fájlkezelõ utasítások. Tipizált és szövegfájlok.
Általában minden magasszintû
programozási nyelv támogatja a háttértárakon lévõ adatállományok
kezelését. Ezt a támogatottságot több szempont is indolkolja nézzük meg a két
legfontosabbat. A program futása során elõállított eredményeket
változókban tároljuk, amelyek a memóriában helyezkednek el. Az eredményeket
kiírathatjuk a képernyõre, a változók tartalmát megõrízhetjük a
program futásának végéig. Azonban a gép kikapcsolásakor a memória tartalma
minden esetben törlésre kerül, tehát a következõ bekapcsoláskor már nem
tudjuk az elõzõleg már kiszámított értékeket, eredményeket
felhasználni. A másik probléma, hogy "a memória mindig kicsi". Tehát
mindig léteznek olyan problémák melynek megoldása során a memória által
biztosított tárolókapacitás kevésnek bizonyul, azaz hamar korlátokba
ütközhetünk.
Ha az adatainkat szeretnénk tartósan megõrízni, akkor igénybe kell
vennünk a háttértárak által biztosított lehetõségeket. Amellett, hogy az
adatainkat a háttértárakon tartósan megõrízhetjük, nagy elõny
még, hogy a háttértárak tárolókapacitása lényegesen meghaladja a memória
kapcitását, tehát sokkal több adatot tudunk itt tárolni.
Az állományok kezelésérõl általában:
Az állományok kezelése az operációs rendszer feladatai közé tartozik. Tehát amikor szeretnénk valamelyik állományt elérni a programunkból, az operációs rendszer szolgáltatásait kell igénybe vennünk (bár ez legtöbb esetben nem tûnik fel, mivel a magasszintû nyelvek tartalmazzák az állományok kezelését segítõ eljárásokat, függvényeket). Az állományok kezelése során minden programozási nyelv és minden operációs rendszer esetén hasonló lépéseket kell végrehajtanunk, nyilván igazodva 424c28e az operációs rendszer és a programozási nyelv sajátosságaihoz (szintaktika, file-ok felépítése, stb). Ezek az általános lépések a következõk:
1. Adatállományok elérésének biztosítása:
Kapcsolatot kell teremteni egy a programozási nyelv által is kezelhetõ
objektum és az fizikai állomány között. Általában egy változón keresztül
történik a kapcsolat létesítése, de más megoldás is elképzelhetõ. Egy
eljárás vagy függvény segítségével rendeljük össze a változót és a fizikai
állományt (részletesen lásd késõbb). Ezt a változót file változónak
szokás nevezni, ugyanis ezzel a változóval tudunk hivatkozni az állományra a
filekezelõ mûveletek során.
2. Adatállományok megnyitása:
Az állomány tartalmát csak akkor tudjuk elérni (olvasni, írni, módosítani), ha
az állományt megnyitjuk, nem elegendõ a logikai kapcsolat kialakítása. A
megnyitás során dõl el, hogy milyen mûvelelteket tudunk majd
végezni az állománnyal (ui. meg lehet nyitni egy állományt csak olvasás, csak
írás vagy mindkettõ céljából, ez általában beállítható).
3. Állománykezelõ mûveletek:
Az elõzõ lépéseken túljutva kezdõdhet az állományokkal
végzett tényleges munka, azaz az állomány tartalmának feldolgozása, módosítása
(olvasási, írási mûveletek). A feldolgozás során szükségünk lehet arra,
hogy az állomány különbözõ részein dolgozzunk, azaz pozícionálnunk kell
az állományban (Pld. egy állományban elõször az elsõ közvetlen
ezután az utolsó sort szeretnénk feldolgozni, az összes többi sort szeretnénk kihagyni),
erre egyes fájltipusoknál lehetõségünk van, más tipusoknál nincs. Minden
programozási nyelv esetében másképpen alakul, hogy az állományokat hogyan
csoportosítja és melyik állományon milyen mûveleteket enged meg.
4. Adatállományok lezárása:
Nagyon fontos lépés, különösen akkor, ha az állomány tartalmát módosítottuk.
Ahhoz, hogy a program által végzett módosításokat megõrízhessük, a
megnyitott állományokat le kell zárni a program befejezése elõtt.
Az adatállományok csoportosítása a Turbo Pascal programozási nyelvben:
A Pascal nyelv az állományoknak három
csoportját különbözteti meg:
- szöveges állományok
- típusos állományok
- típusnélküli állományok
A háromféle állománytípus kezelése során
jelentõs eltéréseket tapasztalhatunk. A három csoport közül az
elsõ kettõt nézzük meg részletesen a továbbiakban.
A szöveges állományok jellemzõi, kezelése:
A szöveges állományok kötetlen
szerkezetû, szekvenciális állományok.
A szöveges állományok bármely szövegszerkesztõvel létrehozhatók, ASCII karakterekbõl
épülnek fel. Kötetlen a szerkezetük, hiszen semmilyen megkötés nincs arra
vonatkozóan, hogy egy szöveges állomány egy sora milyen hosszú lehet, illetve
az is lehetséges, hogy a szöveges állomány sorai eltérõ hosszúságúak. A
kötetlen szerkezet nagy szabadságot enged meg a szöveges állományok létrehozása
során, azonban ennek következményeképpen a programok csak egymás után sorban
dolgozhatják fel az állományban tárolt adatokat. Ez azt jelenti - ahogyan arra
már korábban utaltam - hogy a szöveges állomány esetén az egymást követõ
adatokat csak sorban tudjuk elérni, tehát az esetleges felesleges adatokat is
fel kell dolgozni, hogy a számunkra fontos adatokat elérhessük (ha csak az
elsõ és az utolsó elõtti sorra volna szükségünk, akkor is végig
kell lépkedni a köztük lévõ sorokon is).
A szöveges állományok feldolgozása során is a fenti négy lépésen leírtakat kell
megvalósítani a Pascal nyelv utasításai által.
A szöveges állományok kezeléséhez kapcsolódó utasítások, függvények:
Assign
eljárás:
A fizikai állomány és a file-változó összerendelése. Szintaxisa: Assign(F,
FNev);
F: Text; - A szöveges állományok eléréséhez használt file-változót Text tipusú
változóként kell deklarálni. Mindig egy változó.
FNev: String; - A fizikai állomány elérési útja és neve. Ha az elérési utat nem
adjuk meg, az aktuális könyvtárban keresi a megadott nevû állományt.
Változó és konstans egyaránt megadható.
Az Assign eljárás mindössze a változó-állomány hozzárendelést valósítja meg,
amely mindössze egy logikai kapcsolatot jelent. Ilyenkor még nem használjuk a
fizikai állományt, tehát filenévként olyan file is megadható, amely még nem
létezik.
Reset
eljárás:
Szöveges állomány megnyitása olvasásra. Szintaxisa: Reset(F);
F: Text; - A szöveges állomány eléréshez használt változó. Minden esetben egy
változót kell megadni.
Az utasítás végrehajtása után az állomány elejérõl tudunk adatokat
olvasni.
Append
eljárás:
Szöveges állomány megnyitása hozzáfûzésre. Szintaxisa: Append(F);
F: Text; - A szöveges állomány eléréshez használt változó. Minden esetben egy
változót kell megadni.
Az utasítás végrehajtása után az állomány végére tudunk adatokat írni.
Rewrite
eljárás:
Új állomány létrehozása, illetve létezõ állomány felülírása. Szintaxisa:
Rewrite(F);
F: Text - A szöveges állomány eléréshez használt változó. Minden esetben egy
változót kell megadni.
A Rewrite eljárás nem kizárólag szöveges állományok esetén alkalmazható, minden
filetipusnál használhatjuk a fent leírt mûveletek elvégzéséhez.
Write
és Writeln eljárás:
Írás a szöveges állományba. Szintaxisa: Write(F, S);
F: Text; - A szöveges állomány eléréshez használt változó. Minden esetben egy
változót kell megadni.
S - A második paraméter típusa nincs deklarálva, mivel szöveg, karakter,
illetve szám tipusú változó vagy konstans egyaránt alkalmazható. Az állományba
írni kívánt szöveg, karakter esetleg szám.
Az eljárás ugyanúgy mûködik, mint a képernyõre történõ írás
esetén, de meg kell adni elsõ paraméterként a file-változót.
Read és
Readln eljárás:
Olvasás a szöveges állományból. Szintaxisa: Read(F, S);
F: Text; - A szöveges állomány eléréshez használt változó. Minden esetben egy
változót kell megadni.
S - A második paraméter típusa nincs deklarálva, mivel szöveg, karakter,
illetve szám tipusú változó (és csak változó) egyaránt alkalmazható. Az
állományból olvasni kívánt szöveg, karakter esetleg szám.
Az eljárás ugyanúgy mûködik, mint a billentyûzetrõl
történõ olvasás esetén, de meg kell adni elsõ paraméterként a
file-változót. Mivel a szöveges állományok szerekezete kötetlen, így
különbözõ "tipusú" adatok tárolására alkalmasak. Tehát egy
szöveges állomány egyik sorában egy egész számot a másik sorában egy lakcimet
is tárolhatunk. Ezért nem biztos, hogy minden esetben megfelelõ tipusú
értéket tud a Read és a Readln eljárás beolvasni. Az eredmény ugyanaz, mint a
billentyûzetrõl történõ hibás adat bevitelekor (szám
helyett szöveget ad meg a felhasználó): a program futási hibával leáll. A
késõbbiekben ismertetésre kerülõ módszerrel ez
kiküszöbölhetõ.
Eof
függvény:
File vége teszt. Szintaxisa: B:= Eof(F);
F: Text; - A file-változó, amely a fizikai állományt azonosítja.
A függvény visszatérési értéke Boolean tipusú. Ha az állomány végén állunk, a
függvény TRUE értéket ad vissza, egyébként értéke FALSE. Az Eof függvény más
állománytipusoknál is alkalmazható.
Eoln
függvény:
Sorvége teszt. Szintaxisa: B:= Eoln(F);
F: Text; - A file-változó, amely a fizikai állományt azonosítja.
A függvény visszatérési értéke Boolean tipusú. Ha egy sor végén állunk, a
függvény TRUE értéket ad vissza, egyébként visszatérési értéke FALSE. Az Eoln
függvényt csak szöveges állományok esetében alkalmazhatjuk (más
állománytipusnál nincs is értelme). Akkor lehet hasznos az alkalmazása, amikor
az állományt karakterenként dolgozzuk fel.
Close
eljárás:
Az állomány lezárása. Szintaxisa: Close(F);
F: Text; - A file-változó, amely a fizikai állományt azonosítja.
Ezzel az eljárással zárhatjuk le a megnyitott állományokat a szükséges
mûveletek elvégzése után. Alkalmazása minden esetben célszerû, de különösen
fontos, amikor valamilyen módosítást végeztünk az állomány tartalmában.
Módosítás esetén, ha az állomány lezárása nélkül fejezzük be a programot, az
elvégzett változatások nem lépnek érvénybe, a fizikai állomány tartalma
változatlan marad.
A szöveges állományok kezelése:
Const Szov: String= 'Ez a szoveg az allomany vegere kerul';
Var F: Text;
S: String;
C: Char;
Begin
Assign(F, 'szoveg.txt');
Reset(F);
Append(F);
Rewrite(F);
While not Eof(F) do
Begin
Readln(F, S);
Read(F, C);
........
End;
Writeln(F, Szov);
Write(F, Szov);
Close(F);
End.
Példák a szöveges állományok használatára:
Olvassuk be egy szöveges állomány elérési
útját és nevét, majd írjuk ki a tartalmát a képernyõre.
(Az állomány feldolgozása soronként történik)
Uses CRT;
Var F: Text;
S: String;
FNev: String;
Begin
ClrScr;
Write('Az allomany neve: ');
Readln(FNev);
Assign(F, FNev);
Reset(F);
If IOResult<0
then Begin
Writeln('Hiba az allomany megnyitasa soran.');
Halt(1);
End;
While not Eof(F) do
Begin
Readln(F, S);
Writeln(S);
End;
Close(F);
End.
Olvassuk be egy szöveges állomány elérési
útját és nevét. Olvassunk be egy tetszöleges karaktert
(vezérlõkarakterek kivéve). Számoljuk meg, hogy a beolvasott karakter
hányszor fordul elõ a szöveges állományban.
(Az állomány feldolgozása karakterenként történik)
Uses CRT;
Var F: Text;
C, K: Char;
FNev: String;
Sum: Longint;
Begin
ClrScr;
Write('Az allomany neve: ');
Readln(FNev);
Write('A keresett karakter: ');
Readln(K);
Sum:= 0;
Assign(F, FNev);
Reset(F);
If IOResult<0
then Begin
Writeln('Hiba az allomany megnyitasa soran.');
Halt(1);
End;
While not Eof(F) do
Begin
Read(F, C);
If UpCase(C)=UpCase(K)
then Sum:= Sum+1;
End;
Close(F);
Writeln('A keresett karakter elofordulasainak szama: ',
Sum);
End.
Az állomány feldolgozása karakterenként történik, ezért az olvasás során a Readln helyett a Read eljárást használjuk. A Sum változóban tároljuk az elõfordulások számát, ezért a változót a feldolgozási ciklusba lépés elõtt le kell nullázni. Az UpCase függvény segítségével a keresett és az állományból olvasott karaktert nagybetûvé alakítjuk, így kiküszöböljük a kis- és nagybetûk megkülönböztetését.
A szöveges állományok szerkezete kötetlen,
bármely szövegszerkesztõ segítségével létrehozhatók. Az állomány
tartalma az ASCII karakterkészlet elemeibõl tevõdik össze. A
kötetlen szerkezet miatt az állományok feldolgozása csak szekvenciális
módszerrel lehetséges, azaz az állomány tartalmát csak soronként (esetleg
karakterenként) dolgozhatjuk fel.
Típusos állományok jellemzõi, kezelése:
A típusos állományok kötött adatszerkezettel
rendelkeznek, lehetõvé téve ezzel a direkt pozícionálást is. Kezelésük
lépései megegyeznek a szöveges állományok kezelésének lépéseivel:
- elõkészületi lépések
- állomány megnyitása
- az állomány adatait kezelõ mûveletek
- állomány lezárása
A típusos állományok elérése is egy változón
keresztül történik, de a változó típusa némelyest különbözik a szöveges
állományoktól. Általános deklarációja: Var F: File of Adattípus;
Az Adattípus helyére azt a típust kell írnunk, amilyen adatokat az állományban
találhatunk.
Példa: Egy egész számokat tartamazó állomány: Var F: File of Integer;
A típusos állományok esetében is el kell végezni a file-változó és a fizikai
file összerendelését, az Assign eljárás segítségével. Hasonlóképpen történik,
mint szöveges állományok esetén: Assign(F, 'C:\SZAMOK.DAT');
A típusos állományok megnyitása minden esetben
a Reset eljárás segítségével történik. A Reset eljárás a típusos állományokat
írásra és olvasásra nyitja meg (alapértelmezés szerint). Tehát itt mindkét
mûvelettípust egyszerre végezhetjük. Példa: Reset(F);
Az állományok megnyithatók csak olvasásra, csak írásra is. Ha a Reset eljárás
alapértelmezett mûködésén módosítani szeretnénk, akkor a FileMode
nevû beépített változó értékét kell megváltoztatnunk a Reset eljárás
meghívása elõtt. A FileMode változó a System unit-ban van deklarálva,
lehetséges értékei:
0 - a Reset eljárás csak olvasásra nyitja meg az állományt.
1 - a Reset eljárás csak írásra nyitja meg az állományt.
2 - a Reset eljárás írásra ÉS olvasásra nyitja meg az állományt. Ez az
alapértemezett mûködés.
A típusos állományok esetében csak a Read és
Write eljárásokat használhatjuk az olvasás, illetve az írás során. A Readln és
Writeln eljárásoknak nem lenne értelme, hiszen az állomány adatai nem sorokba
vannak elrendezve. Az eljárásokat a szöveges állományoknál már megismert módon
használhatjuk:
Read(F, V); - olvasás az állományból.
Write(F, V); - írás az állományba.
A V paraméter típusának meg kell egyezni a file-változó deklarációjában
szereplõ alaptípussal. (File of Integer tipusú állománynál V típusa is
kötelezõen Integer kell legyen.)
A típusos állományok esetén
lehetõségünk van a direkt pozícionálásra, nem kötelezõ az
adatokat egymás után feldolgozni. A file-mutató (lásd késõbb) mozgatása
a Seek eljárás segítségével történik. A Seek eljárásnak paraméterként meg kell
adni, hogy az állomány hanyadik rekordjára szeretnénk mozgatni a file-mutatót.
A rekordok sorszámozása 0-val kezdõdik.
Példa: Seek(5);
A Seek eljárásnak csak olyan számot adhatunk meg, amely 0 és az állomány utolsó
rekordjának sorszáma közé esik, ha a szám ezen az intervallumon kívül esik, a
program futási hibával leáll. A futási hiba kiküszöbölhetõ a már
említett $I direktíva kikapcsolása segítségével. Ha a pozícionálás sikertelen
volt, az IOResult változó értéke 0-tól különbözõ lesz.
Visszatérve a file-mutatóra: A file-mutató egy olyan változó, amely megmutatja, hogy az állományban melyik lesz a következõ feldolgozásra kerülõ rekord. Ennek a mutatónak a pozícióját teszteli az Eof függvény is. A file-mutató nem keverendõ össze a Pointer típussal, mivel a file-mutató egy Longint típusú érték. A programozónak az esetek legnagyobb százalékában nem kell a file-mutatóval közvetlenül foglalkozni, a Pascal eljárásain, függvényein keresztül indirekt módon kezeljük.
A típusos állományoknál is használhatjuk az
Eof függvényt az állomány végének tesztelésére. Mivel az adatok nem sorokba
vannak szervezve, nyilván az Eoln függvénynek nincs értelme, ezért típusos
állományoknál nem használható.
Példák a típusos állományok használatára:
Hozzunk létre egy állományt, amelyet rekord típusú adatokkal töltünk fel!
Uses CRT;
Type Szemely= Record
Nev:
String;
Lakcim: String;
Eletkor: Byte;
End;
Var F: File of Szemely;
Adat: Szemely;
New: Boolean;
Ch: Char;
Begin
Assign(F, 'C:\ADAT.DOC');
Rewrite(F);
If IOResult<0
then Begin
Writeln('Hiba lepett fel az allomany letrehozasa soran');
Halt;
End;
Repeat
Write('Nev: ');
Readln(Adat.Nev);
Write('Lakcim: ');
Readln(Adat.Lakcim);
Write('Eletkor: ');
Readln(Adat.Eletkor);
Write(F, Adat);
Write('Uj rekord (I/N): ');
Readln(Ch);
If (Ch='I') or (Ch='i')
then New:= True
else New:= False;
Until not New;
Close(F);
End.
A típusos állomány típusának meghatározásánál
(File of Adattipus) csak egyszerû tipusokat használhatunk, tehát ha
összetett tipusokkal (rekord, tömb) szeretnénk dolgozni, akkor a típust a
típusdeklarációs részben elõre deklarálni kell. A program addig olvassa
be az adatokat, amíg a beolvasás után feltett kérdésre Igen (I) választ adunk.
Olvassuk be és jelenítsük meg a képernyõn az elõbbi állomány tartalmát.
Uses CRT;
Type Szemely= Record
Nev:
String;
Lakcim: String;
Eletkor: Byte;
End;
Var F: File of Szemely;
Adat: Szemely;
Begin
Assign(F, 'C:\ADAT.DOC');
Reset(F);
If IOResult<0
then Begin
Writeln('Hiba lepett fel az allomany megnyitasa soran');
Halt;
End;
ClrScr;
Writeln('Az ADAT.DOC allomany tartalma:');
Wrteln('-------- ----- ------ ---');
While not Eof(F) do
Begin
Read(F,
Adat);
Writeln('Nev: ', Adat.Nev);
Writeln('Lakcim:
', Adat.Lakcim);
Writeln('Eletkor: ', Adat.Eletkor);
Writeln;
End;
Close(F);
End.
Keressük meg és írassuk ki azoknak a személyeknek az adatait, akik idõsebbek 20 évnél. Használjuk fel az elõbbi példákban létrehozott állományt.
Uses CRT;
Type Szemely= Record
Nev:
String;
Lakcim: String;
Eletkor: Byte;
End;
Var F: File of Szemely;
Adat: Szemely;
Begin
Assign(F, 'C:\ADAT.DOC');
Reset(F);
If IOResult<0
then Begin
Writeln('Hiba lepett fel az allomany megnyitasa soran');
Halt;
End;
ClrScr;
Writeln('Az ADAT.DOC allomany tartalma:');
Wrteln('-------- ----- ------ ---');
While not Eof(F) do
Begin
Read(F,
Adat);
If
Adat.Eletkor20
then Begin
Writeln('Nev: ', Adat.Nev);
Writeln('Lakcim: ', Adat.Lakcim);
Writeln('Eletkor: ', Adat.Eletkor);
Writeln;
End;
End;
Close(F);
End.
Találat: 1630