PP1 wyklad 10


Podstawy Programowania
Wykład dziesiąty:
Pliki
1.Pliki  podstawowe wiadomości
Jeśli dane, które przetwarza lub produkuje program komputerowy mają być
dostępne po zakończeniu jego pracy, to muszą one zostać przechowane
w pamięci masowej komputera. Pamięć tego typu jest urządzeniem
pozwalającym zachować zapisane w niej informacje w sposób trwały. Takimi
urządzeniami są np.: dyski twarde, płyty CD, DVD i pamięci typu Flash. Każde
z tych urządzeń przechowuje dane w inny sposób. Aby ujednolicić sposób
korzystania ze zgromadzonych na nich informacji wprowadzono specjalną
strukturę danych nazywaną plikiem. Pliki gwarantują ten sam sposób
korzystania z informacji niezależnie od tego, czy znajdują się one na dysku
twardym, w pamięci operacyjnej, czy innym nośniku. W przypadku większości
współczesnych systemów komputerowych urządzenia zewnętrzne, takie jak
klawiatura, ekran, dysk twardy, napęd CD, drukarki są  widziane przez
programy komputerowe właśnie jako pliki. Język Pascal pozwala korzystać
z trzech rodzajów plików: plików tekstowych, plików binarnych zdefiniowanych1
i plików binarnych niezdefiniowanych (amorficznych). Pliki, niezależnie do
którego rodzaju należą, składają się zawsze z pewnych elementów.
W przypadku plików tekstowych tymi elementami są wiersze, czyli ciągi znaków
zakończone znakami końca wiersza (w przypadku Turbo Pascala są to znaki
#13#10). Wynika stąd, że wiersze te mogą mieć różny rozmiar. Elementami
plików binarnych zdefiniowanych są wartości określonego przez nas typu. Mogą
to być wartości typu byte, integer, real, a nawet typu rekordowego. W plikach
amorficznych (binarnych niezdefiniowanych) wartości, które są przechowywane
nie mają określonego typu. Cały plik jest podzielony na porcje o ustalonej
wielkości, zwane blokami. Dla wszystkich typów plików możemy stosować
dostęp sekwencyjny, tzn. taki, w którym aby przeczytać lub zapisać element
znajdujący się w dowolnym miejscu pliku musimy przeczytać wszystkie
elementy znajdujące się przed nim. W przypadku plików binarnych możemy
mieć również swobodny dostęp do elementów plików2. Pliki binarne możemy
zatem potraktować jako tablice, których rozmiar jest zmienny.
2.Typy plików
W Turbo Pascalu jedynym typem plików, który powinniśmy zdefiniować jest typ
pliku binarnego zdefiniowanego. Typ pliku binarnego zdefiniowanego określamy
w sekcji type programu lub podprogramu według wzorca:
nazwa_typu_pliku = file of nazwa_typu_elementu_pliku;
1 Nazywanych krótko plikami binarnymi.
2 Tzn. możemy wskazać dowolny element, który chcemy przeczytać/ zmodyfikować, bez
konieczności przeglądania elementów je poprzedzających.
2
Przykładowo, plik binarny, którego elementy byłyby typu integer miałby na-
stępującą definicję typu:
type
plik = file of integer;
Pliki amorficzne, jak również tekstowe mają już zdefiniowane typy, które są
częścią języka i nie musimy im nadawać nowej nazwy (choć istnieje taka możli-
wość). Typem pliku binarnego niezdefiniowanego jest po prostu file, a typem
pliku tekstowego jest text.
3. Zmienne plikowe
Podobnie jak zmienne innych typów zmienne plikowe możemy deklarować
w sekcji var programu lub podprogramu. W przypadku plików binarnych
zdefiniowanych należy wcześniej zdefiniować typ takiej zmiennej według za-
mieszczonego wyżej wzorca, gdyż zmiennych plikowych tego rodzaju o ano-
nimowych typach nie będziemy mogli przekazać przez parametr. Nie wymagają
tego zmienne plikowe związane z plikami tekstowymi lub amorficznymi. Nie
możemy deklarować zmiennych plikowych zainicjalizowanych. Jedynym spo-
sobem, w jaki możemy przekazać zmienną plikową do procedury lub funkcji za
pomocą parametru jest przekazanie przez zmienną (adres).
4.Operacje na plikach
Zanim będziemy mogli zapisać lub odczytać informacje z pliku musimy wy-
konać dodatkowe czynności. Schemat korzystania z pliku może być przedsta-
wiony następująco:
1. skojarzenie zmiennej z plikiem,
2. otwarcie pliku,
3. przetwarzanie informacji zawartych w pliku,
4. zamknięcie pliku.
Należy zaznaczyć, że przy wykonywaniu prawie każdej z tych operacji mogą
pojawić się wyjątki3, które należy obsłużyć. Powyższe operacje są realizowane
za pomocą różnych funkcji i procedur. Nazwy tych podprogramów mogą się
3 Inaczej nazywane błędami, choć nie jest to nazwa w pełni adekwatna.
3
różnić w zależności od typu pliku, na którym zostaną użyte. Zostały one
zebrane w tabelkę:
Nazwa operacji Skojarzenie Otwarcie Odczyt Zapis Zamknięcie
Typ pliku
rewrite
read write
Plik tekstowy assign reset close
readln writeln
append
rewrite
Plik binarny assign read write close
reset
rewrite
Plik amorficzny assign blockread blockwrite close
reset
Procedura assign działa w ten sam sposób dla wszystkich typów plików. Wiąże
ona zmienną plikową z nazwą pliku. Pierwszym parametrem jej wywołania jest
nazwa zmiennej plikowej, a drugim ciąg znaków będący nazwą pliku. W Turbo
Pascalu4 nazwa pliku składa się maksymalnie z jedenastu liter lub cyfr.
Pierwszych osiem liter jest nazwą właściwą, a trzy ostatnie stanowią tak zwane
rozszerzenie, które określa zawartość pliku. Obie te części nazwy pliku są
rozdzielone kropką. Istnieją też pliki o specjalnych nazwach, które związane są
z urządzeniami. Takimi plikami są LPR1 lub PTR związane z drukarką, CON
związany z konsolą (klawiatura + ekran monitora), COM1 związany z portem
szeregowym. Po skojarzeniu zmiennej plikowej z plikiem możemy go otworzyć.
W tym wypadku zachowanie poszczególnych procedur otwierających różni się
w zależności od typu otwieranego pliku. Dla plików tekstowych procedura
rewrite tworzy nowy plik, który można wyłącznie zapisywać. Procedura reset
otwiera istniejący plik w trybie tylko do odczytu, natomiast procedura append
otwiera istniejący plik w trybie do dopisywania, co oznacza, że nowe informacje
będą w tym pliku zapisywane za już istniejącymi. Wszystkie te procedury, jako
parametr wywołania przyjmują zmienną plikową skojarzoną z plikiem, który
ma zostać otwarty. W przypadku plików binarnych zdefiniowanych procedura
rewrite5 tworzy nowy plik, natomiast procedura reset otwiera plik, który już
istnieje. W obu przypadkach możliwe jest odczytywanie i zapisywanie do pliku.
Podobnie, jak poprzednio jedynym parametrem wywołania tych procedur są
zmienne plikowe, na których operacja ma zostać wykonana. W przypadku
plików amorficznych, procedury rewrite i reset mają takie samo działanie, jak
dla plików binarnych zdefiniowanych, ale mogą przyjmować dodatkowy
parametr wywołania, będący liczbą określającą wielkość (w bajtach) bloku, jaki
4 Dokładniej w systemie DOS, dla którego kompilator Turbo Pascala jest przeznaczony.
5 Jeśli procedura rewrite zostanie użyta dla istniejącego pliku, to skasuje jego zawartość,
niezależnie od jego typu.
4
można jednorazowo zapisać lub odczytać z takiego pliku. Jeśli sami nie
określimy rozmiaru bloku, to zostanie przyjęty rozmiar domyślny równy 128
bajtów. Do odczytu plików tekstowych możemy zastosować znane już nam
procedury read i readln. Domyślnie te procedury związane są z plikiem
o nazwie Input, czyli po prostu z klawiaturą6. Jeśli jednak jako pierwszy
parametr ich wywołania podamy nazwę zmiennej plikowej, to odczyt zamiast
z klawiatury będzie odbywał się z pliku. Po nazwie zmiennej plikowej występuje
lista składająca się co najmniej z jednej zmiennej do której będą wczytane
informacje z pliku. Różnica między readln i read polega na tym, że pierwsza
odczytuje cały wiersz znaków, zakończony znakami końca wiersza, natomiast
druga czyta tyle informacji, ile wynika z liczby i typu zmiennych do których one
będą zapisywane. W przypadku plików binarnych zdefiniowanych odczyt
możliwy jest wyłącznie za pomocą procedury read. Pierwszym parametrem
wywołania tej procedury jest zmienna plikowa, natomiast następnymi zmienne
(w liczbie co najmniej jeden), do których informacje będą zapisane. Typy tych
zmiennych muszą być takie same lub zgodne z typem elementów pliku.
W przypadku plików amorficznych odczyt jest możliwy tylko za pośrednictwem
procedury blockread. Ta procedura może przyjmować trzy lub cztery parametry
wywołania. Pierwszym jest zmienna plikowa, drugim zmienna do której ma
zostać zapisana informacja, a trzecim zmienna, wartość lub wyrażanie typu
word, określające ile bloków chcemy z pliku odczytać. Czwarty parametr
wywołania jest opcjonalny i jest nim zmienna typu word, w której jest
zapisywana liczba faktycznie przeczytanych bloków. Jeśli nie umieścimy tego
argumentu na liście parametrów wywołania procedury blockread, to
w przypadku, kiedy zostanie odczytana mniejsza niż chcieliśmy liczba bloków
z pliku program zakończy się natychmiast sygnalizując błąd wykonania. Jeśli
przekażemy czwarty parametr, to możemy obsłużyć ten wyjątek. Zapis do pliku
również odbywa się w różny sposób, w zależności od rodzaju pliku. Do plików
tekstowych możemy zapisywać informacje za pomocą write i writeln. Podobnie
jak w przypadku procedury read i readln domyślnie są one skojarzone
z plikiem Output, czyli ekranem monitora7. Jeśli jako pierwszy parametr
wywołania tej procedury umieścimy zmienną plikową, to zapis informacji
nastąpi do pliku z nią związanego. Za tym parametrem, mogą występować inne
będące zmiennymi, wyrażeniami lub wprost - wartościami, które mają zostać
zapisane do pliku. Procedura writeln zapisuje do pliku wiersze zakończone
znakami końca wiersza. Natomiast procedura write nie umieszcza w pliku tych
znaków samodzielnie. Do zapisu plików binarnych zdefiniowanych używana
jest wyłącznie procedura write. Sposób wywołania tej procedury jest taki sam,
jak w przypadku plików tekstowych. Pliki amorficzne mogą być zapisywane
6 Plik skojarzony z klawiaturą nazywany jest również standardowym wejściem.
7 Plik ten nazywany jest również standardowym wyjściem.
5
przy pomocy procedury blockwrite. Jej parametry wywołania są takie same, jak
w przypadku procedury blockread, z tym że odnoszą się one do zapisu, a nie
odczytu. Operacja zamykania pliku jest przeprowadzana w ten sam sposób dla
wszystkich rodzajów plików  przy pomocy procedury close. Jedynym
parametrem wywołania tej procedury jest zmienna plikowa.
5.Inne operacje związane z plikami
W języku Pascal zdefiniowano szereg procedur i funkcji, które wykonują inne
pomocne operacje na plikach, niż te, które opisano wyżej. Oto niektóre
z nich wraz, z krótkim opisem:
funkcja eof zwraca wartość true, jeśli został osiągnięty koniec pliku.
Działa dla wszystkich typów plików. Jej parametrem wywołania jest
nazwa zmiennej plikowej, jeśli zostanie ona pominięta, to wywołanie to
będzie się odnosiło do standardowego wejścia,
funkcja seekeof działa podobnie, ale tylko dla plików tekstowych
i ignoruje znaki białe (spacja, powrót karetki, itp.),
funkcja eoln działa jedynie dla plików tekstowych i zwraca true, jeśli
został osiągnięty koniec wiersza,
funkcja seekeoln działa podobnie, ale ignoruje znaki spacji i tabulacji,
jest przeznaczona wyłącznie dla plików tekstowych,
funkcja filesize zwraca liczbę elementów pliku binarnego lub liczbę
bloków pliku amorficznego,
funkcja filepos działa dla plików binarnych i amorficznych, zwraca
wartość typu longint, która oznacza pozycję wskaznika pliku,
procedura seek ustawia pozycję wskaznika pliku8. Pierwszym
argumentem jej wywołania jest nazwa zmiennej plikowej, drugim wartość
nowej pozycji wskaznika pliku. Wartość ta jest typu longint. Procedura
seek jest przeznaczona dla plików binarnych i amorficznych,
procedura truncate  ucina plik począwszy od bieżącej pozycji wskaznika
pliku, działa dla plików binarnych i amorficznych,
8 O wskazniku pliku możemy myśleć jak o indeksie tablicy. Jest on przesuwany automatycznie
po wykonaniu każdego odczytu lub zapisu zawartości pliku.
6
funkcja ioresult zwraca kod wykonania operacji na pliku, jeśli operacja
przebiegła prawidłowo, to kod ten jest równy zero, w przeciwnym
przypadku jest to wartość różna od zera, aby ta funkcja działała
prawidłowo należy wyłączyć dyrektywę $I kompilatora.
Opisana wcześniej funkcja eof jest dosyć często stosowana, kiedy
konstruujemy pętlę, w której umieszczamy instrukcje odczytujące z pliku. Jeśli
jest to pętla while, to warunek w tej pętli ma postać: not eof(zp), natomiast jeśli
jest to pętla repeat ... until, to warunkiem zakończenia jest eof(zp).
W przypadku plików binarnych i amorficznych możliwe jest użycie do odczytu
pętli for. Poniżej znajdują się przykłady programów operujących na
odpowiednio: plikach tekstowych, binarnych i amorficznych.
program pliki_tekstowe;
uses crt;
var T:text;
procedure zapisz(var F:text);
{Zapisuje do pliku tekstowego 10 wierszy pobranych od użytkownika.}
var
a:string[80];
i:byte;
begin
rewrite(F);
for i:=1 to 10 do
begin
readln(a);
writeln(F,a);
end;
close(f);
end;
procedure odczytaj(var F:text);
{Odczytuje z pliku tekstowego 10 wierszy.}
var
7
a:string[80];
begin
reset(F);
repeat
readln(f,a);
writeln(a);
until eof(f);
close(f);
end;
begin
clrscr;
assign(T,'dane.txt');
zapisz(T);
clrscr;
odczytaj(T);
readln;
end.
Zmienna plikowa, typu text jest kojarzona z plikiem o nazwie dane.txt w bloku
głównym programu. Plik ten tworzony jest w procedurze zapisz, w wyniku
wywołania procedury rewrite. W tej też procedurze do pliku zapisywanych jest
dziesięć wierszy (pętla for) zawierających ciągi znaków podane przez
użytkownika (o wielkości maksymalnie 80 znaków). Procedura odczyt odczytuje
te dane z tego samego pliku. Odczytanie i wyświetlenie na ekran odbywa się
wewnątrz pętli repeat. W obydwu procedurach ostatnią wykonywaną instrukcją
jest zamknięcie pliku.
program plik_binarny;
uses
crt;
type
rec = record
x,y:integer;
end;
pl_rec = file of rec;
8
var
plik:pl_rec;
procedure zapisz(var f:pl_rec);
var
r:rec;
i:byte;
begin
{$I-}rewrite(f);{$I+}
if ioresult <> 0 then exit;
for i:=1 to 5 do
begin
with r do
begin
writeln('Podaj x');
readln(x);
writeln('Podaj y');
readln(y);
end;
write(f,r);
end;
close(f);
end;
procedure append_bin(var f:pl_rec);
begin
{$I-}reset(f);{$I+}
if ioresult <> 0 then halt(1);
seek(f,filesize(f));
end;
9
procedure dopisz(var f:pl_rec);
var
r:rec;
begin
writeln('Podaj x');
readln(r.x);
writeln('Podaj y');
readln(r.y);
append_bin(f);
write(f,r);
close(f);
end;
procedure wypisz(var f:pl_rec);
var
r:rec;
begin
{$I-}reset(f);{$I+}
if IOResult <> 0 then exit;
while not eof(f) do
begin
read(f,r);
write(r.x,' ');
write(r.y);
writeln;
end;
close(f);
end;
begin
clrscr;
assign(plik,'dane.dat');
zapisz(plik);
writeln('Naciśnij Enter.');
readln;
10
clrscr;
wypisz(plik);
writeln('Naciśnij Enter.');
readln;
clrscr;
dopisz(plik);
wirteln('Naciśnij Enter.');
readln;
wypisz(plik);
writeln('Naciśnij Enter.');
readln;
end.
Powyższy program przetwarza informacje zawarte w pliku binarnym
zdefiniowanym, którego elementami są rekordy. Taki rodzaj pliku nazywa się
krótko plikiem rekordowym. Każdy rekord zawiera dwa pola x i y, które
przechowują liczby całkowite. Zadaniem programu jest utworzenie pliku
o nazwie dane.dat, zapisanie do niego pięciu rekordów zawierających dane
pobrane od użytkownika, zamknięcie go, następnie ponowne otwarcie,
dopisanie jednego rekordu na końcu tego pliku i wypisanie zawartości
wszystkich rekordów z pliku na ekran. Warto zwrócić uwagę na definicję pliku
rekordowego, jak również na procedurę append_bin. Ponieważ procedura
append działa tylko dla plików tekstowych, w programie została zdefiniowana
osobna procedura dla plików binarnych zdefiniowanych. Otwiera ona taki plik
przy pomocy reset i ustawia jego wskaznik za pomocą procedury seek za
ostatnim elementem pliku. Jego położenie jest ustalane za pomocą funkcji
filesize  elementy pliku są numerowane od zera, więc pozycja ostatniego
elementu ma wartość równą liczbie elementów w pliku minus jeden. Warto
również zauważyć, że wyjątki jakie mogą spowodować procedury otwierania
plików są obsługiwane za pomocą funkcji ioresult. Aby nie były one
obsługiwane domyślnie przez kompilator należy wyłączyć przed wykonaniem
danej operacji na pliku dyrektywę $I kompilatora ({$I-}), a następnie włączyć ją
po wykonaniu tej operacji ({$I+}). Podobnie można obsługiwać wyjątki
pochodzące od innych operacji na pliku, ale w ich przypadku w programie
została zostawiona obsługa domyślna. Funkcja ioresult może odczytać kod
błędu tych operacji tylko przy wyłączonej dyrektywie $I.
11
program plik_amorficzny_i_tablica;
uses
crt;
type
tablica_losowa = array [1..1000] of word;
var
tl:tablica_losowa;
pl:file;
procedure wypelnij_i_zapisz(var F:file; var x:tablica_losowa);
{Wypełnia i zapisuje do pliku amorficznego tablicę 1000 elementów typu word.}
var
l,i:word;
begin
randomize;
for i:=1 to 1000 do x[i] := random(100);
for i:=1 to 1000 do write(x[i]:4);
{$I-}rewrite(F,sizeof(x));{$I+}
if IOResult <> 0 then exit;
blockwrite(F,x,1,l);
if l<>1 then exit;
close(F);
end;
procedure odczytaj_i_pokaz(var F:file; var x:tablica_losowa);
{Wypełnia tablicę 1000 elementów typu word danymi z pliku.}
var
l,i:word;
begin
{$I-}reset(F,sizeof(x));{$I+}
if IOResult <> 0 then exit;
blockread(F,x,1,l);
if l<>1 then exit;
for i:=1 to 1000 do write(x[i]:4);
12
close(F);
end;
begin
assign(pl,'tablica.dat');
clrscr;
wypelnij_i_zapisz(pl,tl);
writeln('Naciśnij Enter.' );
readln;
clrscr;
odczytaj_i_pokaz(pl,tl);
writeln('Naciśnij Enter.' );
readln;
end.
Ten program wypełnia tablice o 1000 elementach typu word i zapisuje ją,
a następnie odczytuje z pliku amorficznego. Warto zwrócić uwagę na sposób
użycia procedur blockread i blockwirte.
13


Wyszukiwarka

Podobne podstrony:
PP1 wyklad
PP1 wyklad 8
PP1 wyklad 3
PP1 wyklad 5
PP1 wyklad 1
PP1 wyklad 2
PP1 wyklad 4
PP1 wyklad 5
PP1 wyklad 9
PP1 wyklad
PP1 wyklad 4
PP1 wyklad
Sieci komputerowe wyklady dr Furtak
Wykład 05 Opadanie i fluidyzacja
WYKŁAD 1 Wprowadzenie do biotechnologii farmaceutycznej

więcej podobnych podstron