Operacje wejścia/wyjścia (fstream.h)Bardzo często zachodzi potrzeba zapisania czegoś do pliku, więc postanowiłem napisać nieco o obsłudze plików korzystając z funkcji zawartych w pliku nagłówkowym fstream.h. Zacznę od deklaracji zmiennej strumieniowej reprezentującej uchwyt do pliku. W zależności od tego jak otwieramy plik korzysta się z typów ifstream - w trybie odczytu, ofstream - w trybie zapisu, fstream - w trybie zapisu/odczytu. Deklaracja wygląda następująco: ifstream pk; ofstream pk; fstream pk; pk jest zmienną strumieniową reprezentującą uchwyt do pliku. Poruszyłem wcześniej pojęcie strumienia. Jeżeli jest stworzona zmienna strumieniowa i otwarcie pliku się powiodło to tym samym zostaje utworzony strumień. Jest on odwzorowaniem pliku wszystko co dotyczy jego dotyczy otwartego pliku, czyli czytanie, zapisywania itp. Otwieranie następuje po wykonaniu metody open na rzecz zmiennej pk. Wygląda to następująco: pk.open(sc, tryb otwierania); - sc jest to zmienna reprezentująca ścieżkę i nazwę pliku + rozszerzenie - tryb otwierania to: ios::in - do odczytu ios::out - do zapisu ios::nocreate - plik nie zostanie otworzony jako pusty ios::binary - tryb zapisu/odczytu binarny (czyt. nie tekstowy) Jeżeli plik jest otwierany w trybie do zapisu i nie użyjemy wyrażenia ios::nocreate to plik zostanie otworzony jako pusty. Podczas otwierania pliku tryby można ze sobą łączyć np. ios::in|ios::nocreate lub ios::in|ios::out|ios::binary. Można również skorzystać z konstruktora klasy np. ofstream i nie używać metody open. Wystarczy jedynie podać nazwę pliku podczas deklaracji. Czyli: ofstream pk("plik.txt",ios::nocreate); Po zakończeniu wszystkich operacji na pliku należy wywołać metodę close na rzecz uchwytu do pliku: pk.close(); Czyli podsumowując najpierw deklarujemy zmienną reprezentującą plik, następnie otwieramy go i po zakończeniu operacji zamykamy: Przykład: #include int main() { ifstream pk; pk.open("autoexec.bat",ios::in|ios::nocreate); ........//jakieś operacje pk.close(); return 0; } Zastosowanie: if(!pk.is_open()) { cout<<"Pliku nie można otworzyć"; return ; } Czas przejść do omówienia funkcji wejścia/wyjścia. Zacznijmy od funkcji get i put. pk.get() - wyprowadza ona jeden znak ze strumieni pk. Jeżeli nie ma już znaków dostarcza kod EOF, który reprezentuje koniec strumienia znaków. pk.get(zn) - wyprowadza ona jeden znak ze strumieni pk i zapisuje w zmiennej zn. Zwraca odnośnik do uchwytu pk. pk.put(zn) - wprowadza do strumienia pk znak reprezentowany przez zmienną zn(typu char). Przykład zastosowania: #include #include int main() { ifstream pl; pl.open("c:\\autoexec.bat",ios::in|ios::nocreate); char zn; while(pk.get(zn)) //dopóki znaki są wyprowadzane z pk to wykonuj cout< return 0; } Uwaga: kiedy nie podamy ścieżki to plik szukany jest w bieżącym katalogu. Następną funkcją będzie getline. pk.getline(bufor,rozmiar) -wyprowadza z pliku jeden wiersz składający się z nie więcej niż ilość znaków reprezentowanych przez zmienną rozmiar. Wyprowadzone znaki są zapisywane w zmiennej bufor(tablica znakowa). Funkcja gcount zwraca ilość wyprowadzonych znaków. Przykład: #include #include const int wiel=100; int main() { ifstream pk; pk.open("c:\\autoexec.bat",ios::in|ios::nocreate); char buf[wiel]; while(pk) \\wykonuj do momentu kiedy stan strumienia będzie dobry { pk.getline(buf,wiel); int ile=pk.gcount(); if(ile>0) cout< return 0; } Kiedy badamy wartość zmiennej strumieniowej jak ma to miejsce wyżej while(pk) .... to jeżeli stan strumienia jest dobry to pk dostarcza wartość true (prawda), w przeciwnym wypadku dostarcza false (fałsz). Cóż można także wyprowadzać i wprowadzać dane przy użyciu operatorów >> i <<. Np. przy operacji pk>>zmienna; jest dostarczany stan strumienia jeżeli wszystko poszło ok. to zwróci true. Przykład: #include int main() { ifstream pk; pk.open("Dane.txt", ios::in|ios::nocreate); char znak; while(pk>>znak) //dopuki stan strumienia dobry .... cout< return 0; } Wiadomo, że przy dużej ilości danych szybciej jest zapisywać lub odczytywać większe ilości niż np. zapisywać bajt po bajcie do pliku. I tak przejdę do funkcji read i write. pk.read(buf,il) - wyprowadza ona ze strumienia il znaków i zapisuje je do tablicy znakowej buf. pk.write(buf,il) - wyprowadza do strumienia il znaków znajdujących się w tablicy znakowej buf. Przykład: #include const int ile=100; char buf[ile]; int main() { ifstream pk; pk.open("dane.dat",ios::in|ios::nocreate); pk.read(buf,ile); pk.close(); return 0; } Funkcje peek i putback. pk.peek() - zwraca ona kod znaku najbliższego nie wyprowadzając go ze strumienia pk.putback(zn) - kładzie do strumienia znak zn. Wykonanie tej funkcji dostarcza odnośnik do uchwytu pk. Przykład: #include int main() { ifstream pk; pk.open("plik.txt",ios::in|ios::nocreate); while(int(pk.peek())!=48) { char zn; pk.get(zn); cout< pk.close(); return 0; } Funkcje tellg, tellp, seekg, seekp. pk.tellg() - zwraca pozycję pliku. Tryb pliku musi być ios::in pk.tellp() - zwraca pozycję pliku. Tryb pliku musi być ios::out pk.seekg(poz) - ustawia plik na pozycji poz. Plik otworzony w trybie ios::in pk.seekp(poz) - ustawia plik na pozycji poz. Plik otworzony w trybie ios::out Przykład: #include int main() { ifstream pk; pk.open("dane.txt", ios::in|ios::nocreate); char zn; while(pk.get(zn)) { cout< if(gdzie==10) pk.seekg(20); } pk.close(); return 0; } Program odczytuje znaki z pliku dane.txt i kiedy dojdzie do dziesiątego to przeskakuje do dwudziestego i dalej odczytuje dane. Funkcja clear() służy do ustawiania stanu strumienia. pk.clear() - ustawia strumień w stan dobry. pk.clear(ios::failbit) - ustawia strumień w stan nie dobry. Przykład: #include int main() { ifstream pk; pk.open("ania.txt",ios::in|ios::nocreate); for(int a=0;a<10;a++) { char zn; while(pk.get(zn)) cout< pk.seekg(0); } pk.close(); return 0; } Program wyrzuca na ekran 10 razy dane zawarte w pliku ania.txt. Po wyświetleniu danych i dojściu do znaku EOF, strumień jest w stanie nie dobrym i funkcja clear ustawia strumień w stan dobry, po czym pozycja pliku jest ustawiana na 0, czyli początek pliku. Operacja ta jest powtarzana 10 razy. Na tej funkcji chciałbym zakończyć. Życzę miłego eksperymentowania. Autorem tekstu jest: Tomasz Urbaniak |