Wstęp do programowania 2 wykład 2 pliki tekstowe i binarne Agata Półrola Wydział Matematyki UŁ 2005/2006 http://www.math.uni.lodz.pl/~polrola
Pliki wewnętrzne i zewnętrzne Dotychczas przy pobieraniu danych korzystaliśmy ze standardowego wejścia (standard input; zazwyczaj była to klawiatura), a wyniki wyprowadzaliśmy na standardowe wyjście (standard output; zazwyczaj ekran)
Istnieje wiele innych źródeł danych wejściowych czy miejsc do wyprowadzenia danych wynikowych (np. dyski, taśmy magnetyczne, łącza komunikacyjne). Nazywa się je plikami zewnętrznymi (external files). Program czyta i zapisuje dane do plików wewnętrznych (internal files). Pliki wewnętrzne są logicznymi miejscami zapisu i pobierania danych
Przed rozpoczęciem odczytu/zapisu danych z plików wewnętrznych program musi skojarzyć je z plikami zewnętrznymi. Jest to nazywane otwarciem pliku wewnętrznego. Skojarzenie to może być różne w różnych wykonaniach programu. Niektóre kompilatory Ady pozwalają na skojarzenie wielu plików wewnętrznych z jednym zewnętrznym, w innych jest to niedozwolone.
Pliki tekstowe i binarne Dotychczas korzystaliśmy z tekstowego wejścia i wyjścia. W ich przypadku pliki są traktowane jako ciągi znaków. Tekstowa operacja wejścia czyta ciąg następujących po sobie znaków, interpretuje je jako wartość pewnego typu i przekazuje tę wartość do programu Tekstowa operacja wyjścia zapisuje sekwencję znaków reprezentujących pewną wartość
Oprócz tekstowych operacji wejścia i wyjścia możliwe są również operacje związane z wewnętrzną reprezentacją danych. W tym przypadku plik jest traktowany jako sekwencja danych pewnego typu. Dane zazwyczaj reprezentowane są w ten sam sposób w pliku i w programie. Operacje wejścia i wyjścia nie muszą przekształcać danych do innego formatu. przykład: odczyt/zapis rekordów
Rodzaje dostępu Pliki tekstowe i niektóre pliki binarne są plikami o dostępie sekwencyjnym (sequential-access files) odczyt danych rozpoczyna się zawsze od początku pliku; zapis jest dokonywany na końcu pliku Niektóre pliki binarne są plikami o dostępie swobodnym (direct-access files) zapis i odczyt może być dokonywany w dowolnym miejscu pliku
Tryby otwarcia pliku Dane mogą być przekazywane z programu do pliku lub z pliku do programu. Dozwolone operacje zależą od trybu otwarcia pliku. Każdy otwarty plik ma pewien bieżący tryb. Niekiedy można go zmienić przez tzw. resetowanie pliku.
tryb in oznacza, że program może czytać dane z pliku (input file) tryb out oznacza, że program może zapisywać dane w pliku pliki o dostępie swobodnym mogą być otwarte w trybie inout, co oznacza, że program może zarówno czytać z nich dane, jak i je zapisywać pliki o dostępie sekwencyjnym mogą być otwarte w trybie append (dopisywania), co oznacza, że program może zapisywać dane do istniejącego pliku, zachowując przy tym jego dotychczasową zawartość
Przegląd pakietów pliki tekstowe: ada.text_io, ada.wide_text_io (pakiety różnią się tylko typem danych są to odpowiednio sekwencje elementów typu character i wide_character). pliki binarne: o dostępie sekwencyjnym: konkretyzacje pakietu ada.sequential_io, o dostępie swobodnym: konkretyzacje pakietu ada.direct_io pakiet ada.streams.stream_io jest podobny do ada.sequential_io, ale pozwala na zapis/odczyt sekwencji bajtów
Korzystanie z w/w pakietów with ada.text_io, ada.wide_text_io; use ada.text_io, ada.wide_text_io; procedure pliki_tekstowe is... with ada.sequential_io, ada.direct_io; procedure pliki_binarne is package int_seq_io is new ada.sequential_io(integer); use int_seq_io; package int_dir_io is new ada.direct_io(integer); use int_dir_io;
Typ plikowy i zdefiniowane tryby otwarcia plików Wszystkie pakiety definiują typ plikowy File_Type i typ wyliczeniowy File_Mode Tryby otwarcia plików: Dla pakietów ada.text_io, ada.wide_text_io, ada.sequential_io: type File_Mode is (In_File, Out_File, Append_File) Dla pakietu ada.direct_io:
Operacje na plikach zewnętrznych Wszystkie pakiety zawierają podprogramy o tych samych nazwach i roli: tworzenie pliku: procedure Create (File: in out File_Type; Mode: in File_Mode := Out_File; Name: in String := ; Form: in String := ); w pakiecie ada.direct_io domyślny tryb to Inout_File Parametry Name i Form określają plik zewnętrzny: jego nazwę i pewne cechy związane z systemem
otwieranie pliku: procedure Open (File: in out File_Type; Mode: in File_Mode; Name: in String; Form: in String := ); Parametr Form może być użyty do określenia pewnych cech charakterystycznych pliku zależnych od systemu, np. czy może być współdzielony, czy system może ograniczyć prawa zapisu/odczytu względem tego pliku itp
zamykanie pliku: procedure Close (File: in out File_Type); procedure Delete (File: in out File_Type); Procedura Close likwiduje powiązanie między plikiem wewnętrznym i zewnętrznym, Delete dodatkowo usuwa zewnętrzny plik Ada nie definiuje co stanie się jeśli nie zamkniemy pliku przy kończeniu programu (nie zamyka ich automatycznie). Brak zamknięcia pliku może (ale nie musi) spowodować utratę zapisywanych do niego danych czy problemy z dostępem do pliku
resetowanie pliku: procedure Reset (File: in out File_Type; Mode: in File_Mode); procedure Reset (File: in out File_Type); Resetowanie odpowiada zamknięciu i ponownemu otwarciu pliku, ewentualnie dodatkowo z nowym trybem.
określenie stanu pliku: function Is_Open (File: File_Type) return Boolean; function Name (File: File_Type) return String; function Form (File: File_Type) return String; function Mode (File: File_Type) return File_Mode;
Wyjątki Status_Error próba skorzystania z pliku wewnętrznego który nie został otwarty lub otwarcia już otwartego pliku Mode_Error próba odczytu z pliku w trybie out lub append albo próba zapisu do pliku w trybie in Name_Error próba skojarzenia pliku wewnętrznego z plikiem zewnętrznym o niepoprawnej nazwie
Device_Error problem ze sprzętem, oprogramowaniem lub nośnikiem udostępniającym usługi wejścia/wyjścia Use_Error próba wykonania operacji wejścia/wyjścia na pliku dla którego jest to niedozwolone (np. ze względu na prawa dostępu w systemie operacyjnym) End_Error próba czytania danych za końcem pliku wejściowego
Data_Error dane wejściowe w formacie innym od oczekiwanego Layout_Error niepoprawne operacje formatowania w przypadku wyjścia tekstowego
plik:file_type; nazwa: string(1..10); n:natural; begin... put( Podaj nazwe pliku: ); get_line(nazwa,n); begin Open(plik, out_file, nazwa(1..n)); exception when Name_Error => Create(plik, out_file, nazwa(1..n)); end;
Operacje wejścia/wyjścia dla plików tekstowych Plik tekstowy jest sekwencją stron (jednej lub więcej), zakończoną znakiem końca pliku. Każda strona jest sekwencją linii (jednej lub więcej), zakończoną znakiem końca strony Każda linia jest ciągiem znaków, zakończoną znakiem końca linii znaki końca zależą od implementacji
Można określić maksymalną długość linii i strony dla pliku wyjściowego (out) Znaki w linii, linie na stronie, strony w pliku są numerowane (zaczynając od 1) Pakiety zawierają typ całkowity Count o zakresie od 0 do pewnej maksymalnej wartości. Numery znaków, linii, stron są typu Count. Pakiety definiują też podtyp Positive_Count typu Count (o zakresie od 1 do Count last).
Określenie bieżącej pozycji w pliku tekstowym: function Page (File: File_Type) return Positive_Count; function Line (File: File_Type) return Positive_Count; function Col (File: File_Type) return Positive_Count; Przykład: with ada.text_io, ada.integer_text_io; use ada.text_io, ada.integer_text_io; put( Biezaca linia: ); put( Integer(Line(plik)) );
Kontrolowanie struktury linii i stron w pliku wyjściowym (out): procedure Set_Line_Length (File: in File_Type; To: in Count); procedure Set_Page_Length (File: in File_Type; To: in Count); procedure New_Line (File: in File_Type; Spacing: in Positive_Count :=1 ); procedure New_Page (File: in File_Type); procedure Set_Col (File: in File_Type; To: in Count); procedure Set_Col (File: in File_Type; To: in Count);
Określenie bieżących ustawień maksymalnej długości linii / strony: function Line_Length (File: File_Type) return Count; function Page_Length (File: File_Type) return Count;
Kolumny, linie i strony w pliku wejściowym (in): procedure Skip_Line (File: in File_Type; Spacing: in Positive_Count:=1); procedure Skip_Page (File: in File_Type); Możemy korzystać z procedur Set_Line i Set_Col, ale ze względu na dostęp sekwencyjny można przesuwać się tylko w przód (tj. zwiększając numer linii / strony)
Sprawdzenie bieżącej pozycji w pliku: function End_of_Line (File: File_Type) return Boolean; function End_of_Page (File: File_Type) return Boolean; function End_of_File (File: File_Type) return Boolean;
Odczyt i zapis do pliku tekstowego procedure Get (File: in File_Type; Item: out Character); procedure Get (File: in File_Type; Item: out String); procedure Put (File: in File_Type; Item: in Character); procedure Put (File: in File_Type; Item: in String); procedure Get_Line (File: in File_Type; Item: out String; Last: out Natural); procedure Put_Line (File: in File_Type; Item: in String);
with ada.text_io; use ada.text_io; procedure odczyt_pliku is plik:file_type; nazwa: string(1..10); n:natural; linia:string(1..100); begin put("podaj nazwe pliku "); get_line(nazwa,n); open(plik,in_file,nazwa(1..n)); while not end_of_file(plik) loop get_line(plik,linia,n); put(linia(1..n));put_line("*"); end loop; end odczyt_pliku;
Pakiety ada.text_io i ada.wide_text_io posiadają pakiety potomne umożliwiające wprowadzanie i wyprowadzanie wartości należących do różnych typów skalarnych (np. typów całkowitych, zmienno- i stałoprzecinkowych) Można zatem odczytywać z plików tekstowych np. dane całkowite (integer), zmiennoprzecinkowe (float) itp. podobnie można odczytywać elementy typu wyliczeniowego
with ada.text_io, ada.integer_text_io; use ada.text_io, ada.integer_text_io; procedure pliki_int is plik:file_type; nazwa:string(1..10); suma:integer:=0; n:integer; begin put("podaj nazwe pliku "); get_line(nazwa,n); open(plik,in_file,nazwa(1..n)); while not end_of_file(plik) loop get(plik,n); put("odczytane: "); put(n); new_line; suma:=suma+n; end loop; put("suma liczb w pliku: "); put(suma); end pliki_int;
with ada.text_io; use ada.text_io; procedure pliki_dni is type dni_tyg is (pon, wt, sr, czw, pt, so, nie); package dni_io is new enumeration_io(dni_tyg); use dni_io; plik:file_type; nazwa:string(1..10); n:integer; d: dni_tyg; begin put("podaj nazwe pliku "); get_line(nazwa,n); open(plik,in_file,nazwa(1..n)); while not end_of_file(plik) loop get(plik,d); put("odczytane: "); put(d); new_line; end loop; end pliki_dni;
Operacje wejścia/wyjścia dla plików binarnych o dostępie sekwencyjnym procedure Read (File: in File_Type; Item: out Element_Type); procedure Write (File: in File_Type; Item: in Element_Type); function End_Of_File (File: File_Type) retun Boolean;
Operacje wejścia/wyjścia dla plików binarnych o dostępie swobodnym procedure Read (File: in File_Type; Item: out Element_Type); procedure Read (File: in File_Type; Item: out Element_Type; From: in Positive_Count);
procedure Write (File: in File_Type; Item: in Element_Type); procedure Write (File: in File_Type; Item: in Element_Type; From: in Positive_Count);
function End_Of_File (File: File_Type) retun Boolean; function Size (File: File_Type) return Count; procedure Set_Index (File: in File_Type; To: Positive_Count); function Index (File: File_Type) return Positive_Count;