Przeczytaj
Metody dostępu do pliku określają, w jaki sposób jest odczytywany fragment danych. Na wybór metody dostępu do pliku najczęściej wpływa jego struktura, jednak może to być także sposób organizacji systemu plików.
Standardowe strumienie wejścia/wyjścia
Standardowy strumień wejścia to dane przekazywane do programu. Nie każdy program go wymaga, np. zadania realizowane przez rozważany program nie muszą wymagać dodatkowego pobierania informacji. Jeżeli strumień danych nie zostanie przekierowany, to odczytywane informacje będą pobierane z terminalu, w którym działa uruchomiony program.
Standardowy strumień wyjścia to strumień danych, do którego zapisywane są informacje wynikające z działania programu. Jeśli strumień nie jest przekierowany, to dane te są wysyłane do terminalu, w którym uruchomiony jest program.
Przekierowanie strumienia wejścia pozwala przekierować odczytywanie danych z klawiatury (która jest domyślnym wejściem) na plik. Analogicznie jest w przypadku strumienia wyjścia: pozwala przekierować wyjście danych z programu zamiast na ekran – do pliku.
Podział plików ze względu na metody dostępu
Pliki o dostępie sekwencyjnym
Pliki o dostępie sekwencyjnym charakteryzują się tym, że aby dostać się do zawartych w takim pliku konkretnych danych, musimy wcześniej odczytać wszystkie dane je poprzedzające. Niemożliwe jest więc rozpoczęcie odczytywania danych w dowolnym miejscu takiego pliku – odczytywanie zawsze zaczynamy na jego początku. Zapis w plikach sekwencyjnych jest natomiast możliwy jedynie przez dodanie nowych danych na końcu pliku.
Jeśli mamy plik, który zawiera tysiąc rekordów bazy danych klientów salonu samochodowego, to aby móc odczytać dane klienta nr 995, musimy wcześniej przeczytać dane wszystkich poprzedzających go kupujących.
Przykłady operacji i funkcji:
zmienna <-- plik (tryb otwarcia pliku)– operacja otwarcia podanego pliku w wybranym trybie (zapis lub odczyt) oraz utworzenia logicznej zmiennej reprezentującej ten plik;koniecPliku(plik)– funkcja zwraca wartość logicznąfałsz, dopóki cały plik nie zostanie odczytany. Jeżeli cały plik zostanie odczytany, wówczas funkcja ta zwraca wartość logicznąprawda;KodDoZnaku(Kod)– funkcja, która jako jedyny parametr ma liczbę typu całkowitego, a wynikiem jej działania jest odpowiadający jej znak;doZnaków(liczba)– funkcja, która jako jedyny parametr ma liczbę typu całkowitego, zamienia podaną w argumencie liczbę całkowitą na łańcuch znaków (konwersja typów);odczytaj z– odczytuje pojedynczą linię pliku tekstowego;zapisz do– pozwala na zapisanie wartości zmiennej do wskazanego pliku lub danych z pliku do wskazanej zmiennej (np. elementu tablicy);Zamknij plik– zamyka dostęp do zawartości pliku.
Pliki o dostępie bezpośrednim (swobodnym)
Pliki o dostępie bezpośrednim charakteryzują się tym, że odczyt danych możemy rozpocząć od dowolnego miejsca w pliku. Nie musimy zatem odczytywać wielu niepotrzebnych danych, tylko od razu otrzymujemy potrzebne informacje.
Dozwolone operacje (poza podstawowymi):
pozycjonowanie – operacja przejścia do dowolnego bloku pliku, bez sekwencyjnego czytania wszystkich bloków poprzedzających.
W przypadku wspomnianej bazy danych klientów salonu samochodowego, korzystając z pliku o dostępie bezpośrednim, jesteśmy w stanie od razu odczytać dane klienta nr 995, bez potrzeby odczytywania zbędnych informacji.
Pliki o dostępie indeksowym
Cechą charakterystyczną plików o dostępie indeksowym jest to, że rekordrekord, który mamy odczytać lub do którego chcemy zapisać dane, identyfikowany jest poprzez przypisany mu klucz. Tego typu rozwiązanie jest szczególnie powszechne w systemach baz danych.
Dozwolone operacje (poza podstawowymi):
przeszukiwanie indeksu.
Rodzaje plików
Pliki tekstowe
Plik tekstowy to jeden z najpopularniejszych rodzajów plików, często wykorzystywany do odczytywania i zapisywania danych. Języki programowania posiadają specjalne funkcje do pracy z takimi plikami (np. funkcje open(nazwaPliku, tryb), readLine() i write() w języku Python, metody klas FileReader i FileWriter w języku Java, metoda getline() klasy ifstream i operator << użyty na obiekcie klasy ofstream w języku C++) . Pliki tekstowe zapisywane są w formie ciągu znaków podzielonego na wiersze. Na końcu każdego wiersza zapisany jest specjalny znak końca wiersza. Jeden znak w ciągu może zajmować od jednego do kilku bajtów w zależności od przyjętego kodowania, np. ASCII lub Unicode. Każdy plik tekstowy zawiera również znaki domyślnie niewyświetlane na ekranie. Jest to np. wspomniany znak końca wiersza, dzięki któremu komputer jest w stanie odczytać w ciągu bajtów, gdzie dany wiersz zawiera znak końca pliku.
Pliki binarne
To wszystkie pozostałe typy plików, między innymi pliki przechowujące obraz, dźwięk, animacje. Pliki binarne są zapisane na komputerze w postaci ciągu bajtów, niezależnie od tego, co jest w nich zawarte. Każdy plik można odczytywać jak plik binarny. Jeśli struktura pliku binarnego zostanie uszkodzona, plik ten staje się niemożliwy do odczytu.
Operacje na plikach
Możemy wyróżnić następujące operacje na plikach tekstowych:
Otwarcie pliku
Gdy programista w swoim kodzie otwiera plik poprzez wykorzystanie zmiennej plikowej, będącej logiczną reprezentacją zbioru danych w programie, system operacyjny tworzy tak zwany deskryptordeskryptor, do którego uchwytuchwyt wykorzystuje programista, aby móc zapisywać bądź odczytywać dane z/do danego pliku. W deskryptorze znajdują się takie informacje, jak np. urządzenie, na którym plik się znajduje, czy choćby sama nazwa pliku. W momencie otwarcia pliku należy podać tryb, w jakim go otwieramy: do zapisu lub do odczytu zależnie od potrzeb.
Zamknięcie pliku
Zamknięcie pliku usuwa jego deskryptor, zwalnia bufor zapisu/odczytu oraz wymusza zapis danych, które zostały w buforze. Zamknięcie pliku zabezpiecza przed utratą danych, gdyż niezapisane dane, które zostały w buforze, zostałyby utracone.
Warto nadmienić, że w wielu językach programowania operacja zamknięcia pliku wykonywana jest automatycznie. Jako przykład możemy podać język C++ i wykorzystywaną w nim do zapisywania i odczytywania danych z pliku klasę fstream. Właśnie jej destruktor realizuje między innymi opisaną operację zamknięcia pliku.
Zapis do pliku
Wyobraź sobie następującą sytuację: pracujesz nad eksperymentami fizycznymi w laboratorium naukowym. Twój program odczytuje co chwilę setki informacji z dwóch czujników – wartości temperatury oraz wilgotności powietrza. Sposobem na to, aby zebrane dane mogły zostać później przeanalizowane, jest zapisanie ich do zewnętrznego pliku.
Przygotujemy program (zapisany za pomocą pseudokodu), realizujący zapis danych zebranych przez czujniki do pliku tekstowego.
Specyfikacja problemu:
Dane:
n– liczba pomiarów wartości temperatury oraz wilgotności powietrza wykonanych przez czujniki; liczba naturalnadaneZCzujnikaA[0..n - 1]– tablica o rozmiarzenprzechowująca zgromadzone dane z czujnika temperatury; tablica liczb rzeczywistychdaneZCzujnikaB[0..n - 1]– tablica o rozmiarzenprzechowująca zgromadzone dane z czujnika wilgotności powietrza; tablica liczb rzeczywistych
Wynik:
dane.txt– plik tekstowy zawierający w każdym wierszu oddzielone spacją dwie liczby rzeczywiste: wyniki pomiaru temperatury oraz wilgotności powietrza (w przedstawionej kolejności).
W programie wykorzystamy dodatkowo dwie funkcje:
doZnaków(liczba)– funkcja, która jako jedyny parametr ma liczbę typu całkowitego, zamienia podaną w argumencie liczbę całkowitą na łańcuch znaków (konwersja typów),
W różnych standardach kodowania, znaki mają różne kody (np. litera A ma kod szesnastkowy 41 w systemie ASCII i kod U+0041 w systemie Unicode). Ponadto różne systemy operacyjne mogą mieć inne konwencje kodowania pewnych znaków w plikach tekstowych. Przykładem takiej sytuacji jest kodowanie znaku końca linii w systemach rodziny Windows i systemach rodziny Linux:
znak końca linii zapisywany jest przez system Linux jako znak LF (Line Feed – kod ASCII 0x0A),
znak końca linii jest zapisywany przez system Windows jako kombinacja dwóch znaków: CR (Carriage Return – kod ASCII 0x0D) i LF (Line Feed – kod ASCII 0x0A).
Pisanie programu rozpoczynamy od otwarcia pliku dane.txt w trybie zapisu oraz utworzenia zmiennej plikowej plik. Następnie korzystając z pętli dla, zapisujemy kolejne wyniki pomiarów (przekonwertowane do ciągów znaków) z obu tablic do reprezentacji logicznej docelowego pliku. Pamiętamy również o spacji pomiędzy liczbami oraz o wprowadzeniu znaku końca linii po każdych dwóch wynikach. Na koniec zamykamy plik.
Oto gotowy program:
Gdy kończymy pracę z plikiem, plik należy zamknąć! Niezamknięcie pliku przed zakończeniem programu może spowodować utratę danych!
Odczyt z pliku
Teraz spróbujmy odczytać dane z pliku dane2.txt i wprowadzić je do nowej tablicy.
Specyfikacja problemu:
Dane:
dane2.txt– plik tekstowy zawierający wyniki pomiarów ciśnienia atmosferycznego; każdy pomiar (1 liczba całkowita) zapisany jest w osobnym wierszuk– liczba pomiarów wartości ciśnienia atmosferycznego zawartych w pliku z danymi; liczba naturalna.
Wynik:
daneZPliku[0..k - 1]– tablica o rozmiarzekprzechowująca zgromadzone dane z czujnika ciśnienia; tablica liczb całkowitych
W ramach analizy procesu odczytu danych z pliku rozłożymy go na dwa przypadki:
Wiemy, że plik ma
kwierszy:
Ponownie pisanie programu rozpoczynamy od otwarcia pliku dane2.txt, jednakże tym razem w trybie odczytu. Następnie wykorzystując zmienną plik, odczytujemy po kolei każdą z k zapisanych liczb (zgodnie z treścią zadania każda jest w osobnym wierszu) oraz zapisujemy je do tablicy daneZPliku[0..k - 1]. Wykorzystujemy do tego pętlę dla.
Oto gotowy program:
Nie znamy liczby wierszy w pliku:
W związku z nieznajomością liczby wierszy w pliku w tym wariancie jesteśmy zmuszeni do wykorzystania w operacjach funkcji koniecPliku(plik), zwracającej wartość logiczną prawda, gdy podczas odczytywania pliku dotarliśmy do jego końca. Wykorzystamy ją w pętli dopóki. Musimy pamiętać, że w związku z zastosowaniem innego typu pętli, niezbędne będzie zdefiniowanie zmiennej sterującej i (oraz zainicjalizowanie jej wartością 0), przechowującej indeks elementu tablicy daneZPliku[0..k - 1], do którego zapiszemy liczbę z pliku. Niezbędne będzie również zastosowanie operacji inkrementacji.
Oto gotowy program:
Słownik
specjalny identyfikator wykorzystywany przez system operacyjny; umożliwia działanie na pliku, to jest zapis, odczyt oraz odczytywanie ewentualnych błędów
zestaw danych, zazwyczaj mający ustaloną wewnętrzną strukturę, stanowiący pewną całość, ale mogący też być częścią większego zbioru podobnych rekordów
struktura danych przechowująca dodatkowe informacje o otwartym pliku