Lekcja 34LEKCJA 34
Operacje wejścia/wyjścia dla plików w C++
Bardziej złożone programy będą zapisywać informacje na plikach i je stamtąd
odczytywać. Jeśli masz doświadczenie w operacjach na plikach w języku C, to
możesz używać podobnych technik w C++. Jak dowiesz się podczas tej lekcji, C++
daje Ci ponadto do dyspozycji zbiór klas obsługujących strumienie plików, które
ułatwiają operacje wejścia/wyjścia dla plików. Pod koniec tej lekcji będziesz
rozumiał następujące zagadnienia podstawowe:
Przy użyciu strumienia pliku wyjściowego możesz zapisywać informacje na pliku
za pomocą operatora wstawiania <<).
Przy użyciu strumienia pliku wejściowego możesz wczytywać informacje z pliku
za pomocą operatora pobierania (>>).
Do otwierania i zamykania plików służą metody klasy plików.
Do wczytywania i zapisywania danych pliku służą operatory wstawiania i
pobierania, a także różne metody klasy plików.
Wiele programów, które utworzysz w przyszłości, będzie szeroko wykorzystywać
pliki. Powinieneś przećwiczyć to na programach przedstawionych podczas tej
lekcji. Jak zobaczysz, operacje na plikach są w C++ bardzo proste.
Zapisywanie wyjścia na strumieniu pliku
Z lekcji 33 wiesz, że strumień cout jest obiektem typu ostream (strumień
wyjściowy). Korzystając z klasy ostream twoje programy mogą realizować operacje
wyjścia na cout przy użyciu operatora wstawiania lub różnych metod klasy, takich
jak cout.put. Plik nagłówkowy iostream.h definiuje strumień wyjściowy cout.
Analogicznie plik nagłówkowy fstream.h definiuje klasę strumienia pliku
wyjściowego pod nazwą ofstream. Przy użyciu obiektów tej klasy twoje programy
mogą realizować wyjście na plik. Na początek zadeklarujmy obiekt typu ofstream
podając nazwę odpowiedniego pliku wyjściowego jako tekst, tak jak tutaj:
ofstream obiekt_pliku ("NAZWPLIK.ROZ");
Gdy podasz nazwę pliku w deklaracji obiektu typu ofstream, to C++ utworzy na
dysku nowy plik o podanej nazwie lub zamaże plik o podanej nazwie już istniejący
na dysku. Przedstawiony poniżej program PLIKWYJ.CPP tworzy obiekt typu ofstream,
a następnie przy użyciu operatora wstawiania wpisuje kilka linii tekstu do pliku
INFKSIAZ.DAT:
#include
void main(void)
{
ofstream plik_ksiazka ("INFKSIAZ");
plik_ksiazka << "Wygraj z C++" << endl;
plik_ksiazka << "Jamsa Press" << endl;
plik_ksiazka << "22.95 zł." << endl;
}
W tym przykładzie program otwiera plik INFKSIAZ.DAT, a następnie pisze w nim
trzy linie przy użyciu operatora wstawiania. Skompiluj i uruchom ten program.
Jeśli pracujesz w środowisku MS-DOS, to możesz przy użyciu polecenia TYPE
wyświetlić zawartość pliku:
C:\> TYPE INFKSIAZ.DAT
Wygraj z C++
Jamsa Press
22.95 zł.
Jak widzimy, operacja zwykłego wyjścia na plik jest bardzo prosta.
Wczytywanie ze strumienia pliku wejściowego
Jak już wiesz, przy użyciu klasy ofstream twoje programy mogą szybko realizować
operacje wyjścia na plik. W analogiczny sposób możesz realizować operacje
wejścia przy. użyciu obiektów typu ifstream. I znowu musisz po prostu utworzyć
obiekt przekazując jako parametr nazwę pliku:
ifstream plik_wejsc ("NAZWPLIK.ROZ");
Przedstawiony poniżej program WEJPLIKU.CPP otwiera plik INFKSIAZ.DAT utworzony w
poprzednim programie, a następnie wczytuje i wyświetla trzy pierwsze słowa w nim
zapisane:
#include
#include
void main(void)
{
ifstream plik_wejsc ("INFKSIAZ.DAT");
char jeden[64], dwa[64], trzy[64];
plik_wejsc >> jeden;
plik_wejsc >> dwa;
plik_wejsc >> trzy;
cout << jeden << endl;
cout << dwa << endl;
cout << trzy << endl;
}
Być może spodziewasz się, że po skompilowaniu i uruchomieniu programu wyświetli
on pierwsze trzy linie pliku. Jednak, podobnie jak strumień cin, strumień pliku
wejściowego przy użyciu spacji oznacza, gdzie kończy się jedna wartość a zaczyna
druga. W rezultacie po uruchomieniu przedstawionego programu otrzymasz na
ekranie następujące wyjście:
C:\> WEJPLIKU
Wygraj
z
C++
W czytywanie pełnej linii pliku wejściowego
Z lekcji 33 wiesz, że program może przy użyciu funkcji cin.getline wczytywać
całą linię z klawiatury. W analogiczny sposób obiekty typu ifstream mogą
wykorzystywać metodę getline do wczytywania linii z pliku wejściowego.
Przedstawiony poniżej program LINIAPIK.CPP przy użyciu funkcji getline wczytuje
wszystkie trzy linie z pliku INFKSIAZ.DAT:
#include
#include
void main(void)
{
ifstream plik_wejsc ("INFKSIAZ.DAT");
char jeden[64], dwa[64], trzy[64];
plik_wejsc.getline (jeden, sizeof(jeden));
plik_wejsc.getline (dwa, sizeof(dwa));
plik_wejsc.getline (trzy, sizeof(trzy));
cout << jeden << endl;
cout << dwa << endl;
cout << trzy << endl;
}
Teraz program wczytuje całą zawartość pliku, ponieważ wiadomo, że składał się on
z trzech linii. Często jednak programy nie będą wiedziały, ile linii zawiera
plik. W takich sytuacjach będą po prostu czytać plik aż do napotkania jego
końca.
Sprawdzanie, czy doszliśmy do końca pliku
Typową operacją wykonywaną w programach jest wczytywanie zawartości pliku aż do
napotkania końca pliku. Do sprawdzania, czy osiągnięty został koniec pliku służy
funkcja eof obiektu. Zwraca ona 0, gdy nie napotkano końca pliku i 1 gdy
osiągnięto koniec pliku. Przy użyciu pętli while programy mogą w następujący
sposób powtarzać operację czytania pliku aż do dojścia do końca pliku:
while (! plik_wejsc.eof())
{
//Instrukcje
}
Program będzie wykonywać instrukcje pętli tak długo, jak długo funkcja eof
będzie zwracać fałsz (0). Przedstawiony poniżej program TESTEOF.CPP przy użyciu
funkcji eof wczytuje zawartość pliku INFKSIAZ.DAT aż do napotkania końca pliku:
#include
#include
void main(void)
{
ifstream plik_wejsc ("INFKSIAZ.DAT");
char linia[64];
while (! plik_wejsc.eof())
{
plik_wejsc.getline (linia, sizeof(linia));
cout << linia << endl;
}
}
W analogiczny sposób następujący program SLOWAEOF.CPP wczytuje po słowie
zawartość pliku aż do napotkania końca pliku:
#include
#include
void main(void)
{
ifstream plik_wejsc ("INFKSIAZ.DAT");
char slowo[64];
while (! plik_wejsc.eof())
{
plik_wejsc >> slowo;
cout << slowo << endl;
}
}
Na koniec przedstawiony poniżej program ZNAKEOF.CPP wczytuje po znaku zawartość
pliku przy użyciu funkcji get aż do napotkania końca pliku:
#include
#include
void main(void)
{
ifstream plik_wejsc ("INFKSIAZ.DAT");
char litera;
while (! plik_wejsc.eof())
{
litera = plik_wejsc.get();
cout << litera << endl;
}
}
Sprawdzanie błędów podczas operacji na plikach
W przedstawionych dotychczas programach zakładaliśmy, że podczas operacji na
plikach nie wystąpiły błędy. Niestety, nie zawsze tak jest. Na przykład, jeśli
otwierasz plik wejściowy, to program musi sprawdzać, czy ten plik istnieje.
Analogicznie, gdy program zapisuje dane na plik, to musisz sprawdzić, czy
operacja została wykonana poprawnie (na przykład przy przepełnieniu dysku nie
można wpisać danych). Do sprawdzania w programach wystąpienia takich błędów
służy funkcja fail obiektów. (Jeśli podczas operacji na pliku nie było błędu, to
funkcja fail zwróci fałsz (0). Jeśli jednak miał miejsce błąd, to ta funkcja
zwróci prawdę.) Na przykład, przy otwieraniu pliku program powinien przy użyciu
funkcji fail sprawdzać, czy wystąpił błąd, czyli:
ifstream plik_wejsc ("NAZWAPLK.DAT");
if (plik_wejsc.fail())
{
cerr << "Błąd otwarcia pliku NAZWAPLK.DAT" << endl;
exit (1);
}
W analogiczny sposób programy powinny sprawdzać, czy zostały poprawnie wykonane
operacje czytania i pisania. Przedstawiony poniżej program TEST_PŁK.CPP przy
użyciu funkcji fail sprawdza poprawność różnych operacji na pliku:
#include
#include
void main(void)
{
char linia[258];
ifstream plik_wejsc ("INFKSIAZ.DAT");
if (plik_wejsc.fail())
cerr << "Błąd otwarcia pliku NAZWAPLK.DAT" << endl;
else
{
while (! plik_wejsc.eof() && (plik_wejsc.fail()))
{
plik_wejsc.getline (linia, sizeof(linia));
if (plik_wejsc.fail())
cout << linia << endl;
}
}
}
Zamykanie pliku, który nie jest już potrzebny
Po zakończeniu programu system operacyjny zamyka otwarte przez Ciebie pliki.
Jednak przyjmij zasadę, że program zamyka plik, który nie jest już potrzebny. Do
zamykania plików służy funkcja close, np.
plik_wejsc.close();
Gdy zamkniesz plik, to dane, które program zapisał na pliku zostaną umieszczone
na dysku komputera, a pozycja dla pliku w katalogu zostanie uaktualniona.
Tryby otwarcia plików
W przykładowych programach przedstawionych podczas tej lekcji operacje pisania i
czytania pliku zaczynały się od początku pliku. Przy pisaniu danych na pliku
wyjściowym możesz jednak dołączać je na końcu pliku. Aby otworzyć plik w trybie
dołączania, musisz przy otwieraniu pliku podać drugi parametr, np.:
ifstream plik_wejsc ("NAZWAPLK.ROZ", ios::app);
W tym przykładzie parametr ios::app (ang. append = dołącz) określa tryb otwarcia
pliku. W bardziej złożonych programach możesz używać trybów otwarcia plików
wymienionych w tabeli 10.
Tabela 10. Tryby otwarcia plikówTryb otwarciaZnaczenie
ios::appOtwiera plik w trybie dołączania umieszczając bieżącą pozycję
pliku na jego końcu.
ios::ateUmieszcza bieżącą pozycję na końcu pliku.
ios::inOtwarcie do wejścia.
ios::nocreateJeśli podany plik nie istnieje, to nie należy go tworzyć i
zwracany jest błąd operacji.
ios::noreplaceJeśli podany plik istnieje, to należy zwrócić błąd operacji.
ios::outOtwardie pliku do wyjścia
ios::truncZamazywanie zawartości istniejącego pliku.
Oto operacja otwarcia pliku do wyjścia w trybie ios::noreplace, który
zabezpiecza przed zamazaniem istniejącego pliku:
Wykonywanie operacji czytania i pisania
Wszystkie przedstawione podczas tej lekcji programy realizowały operacje na
plikach dla tekstów. W bardziej złożonych programach może się zdarzyć tak, że
będziesz chciał wczytywać lub zapisywać tablice i struktury . Do tego służą
funkcje read i write. Przy wywołaniach tych funkcji należy podawać bufor danych
i rozmiar bufora w bajtach:
plik_wejsc.read(bufor, ziceof(bufor));
plik_wyjsc.write(bufor, ziceof(bufor));
Przedstawiony poniżej program WYJSTR.CPP przy użyciu funkcji write zapisuje
zawartość struktury w pliku PRAC.DAT:
#include
#include
void main(void)
{
struct pracownik {
char imie_nazwisko[64];
int wiek;
float zarobki;
} prac = {"Jan Kowalski", 33, 25000.0};
ofstream plik_prac ("PRAC.DAT");
plik_prac.write ((char *) &prac, sizeof(pracownik));
}
Funkcja write powinna otrzymywać wskaźnik do tekstu. (char *) to konwersja,
dzięki kt órej kompilator będzie wiedział, że przekazujesz wskaźnik do innego
typu. w analogiczny sposób przedstawiony poniżej program WEJSTR.CPP przy użyciu
metody read wczytuje z pliku informacje o pracowniku:
#include
#include
void main(void)
{
struct pracownik {
char imie_nazwisko[64];
int wiek;
float zarobki;
} prac = {"Jan Kowalski", 33, 25000.0};
ifstream plik_prac ("PRAC.DAT");
plik_prac.read ((char *) &prac, sizeof(pracownik));
cout << prac.imie_nazwisko << endl;
cout << prac.wiek << endl;
cout << prac.zarobki << endl;
}
Zapamiętaj
W bardziej złożonych programach będziesz często wykonywał operacje na plikach.
Poświęć nieco czasu na eksperymenty z programami przedstawionymi podczas tej
lekcji. Podczas lekcji 35 nauczysz się poprawiać szybkość działania programów
dzięki funkcjom inline. Zanim jednak przejdziemy do lekcji 35 upewnij się, że
opanowałeś już następujące zagadnienia podstawowe:
Plik nagłówkowy fstream.h definiuje klasy ifstream i ofstream, przy użyciu
których możesz w swoich programach realizować operacje wejścia i wyjścia dla
plików.
Aby otworzyć plik do operacji wejścia lub wyjścia, należy zadeklarować obiekt
typu ifstream lub ofstream przekazując jego konstruktorowi nazwę odpowiedniego
pliku.
Po otwarciu pliku do wejścia lub wyjścia program może wczytywać lub zapisywać
dane przy użyciu operatora pobierania (>>) lub wstawiania (<<).
Programy mogą realizować wejście i wyjście znakowe dla pliku przy użyciu
funkcji get i put.
Przy użyciu funkcji getline programy mogą wczytywać całą linię pliku.
Większość programów wczytuje zawartość pliku aż do napotkania końca pliku. Do
sprawdzania, czy osiągnięto koniec pliku służy funkcja eof.
Programy po wykonaniu operacji na pliku powinny sprawdzać, czy została ona
poprawnie zrealizowana. Służy do tego funkcja fail.
Jeśli program ma wczytywać lub zapisywać dane, takie jak struktura lub
tablica, to powinien wywoływać funkcje read lub write.
Program po zakończeniu korzystania z pliku powinien go zamykać przy użyciu
funkcji close.
WsteczSpis treściDalej
Wyszukiwarka
Podobne podstrony:
Kris Jamsa Wygraj Z C lekcja32
Kris Jamsa Wygraj Z C lekcja 5
Kris Jamsa Wygraj Z C lekcja23
Kris Jamsa Wygraj Z C lekcja38
Kris Jamsa Wygraj Z C lekcja35
Kris Jamsa Wygraj Z C lekcja20
Kris Jamsa Wygraj Z C lekcja27
Kris Jamsa Wygraj Z C lekcja34
Kris Jamsa Wygraj Z C lekcja18
Kris Jamsa Wygraj Z C lekcja17
Kris Jamsa Wygraj Z C lekcja25
Kris Jamsa Wygraj Z C lekcja14
Kris Jamsa Wygraj Z C lekcja36
Kris Jamsa Wygraj Z C lekcja 4
Kris Jamsa Wygraj Z C lekcja 7
Kris Jamsa Wygraj Z C lekcja30
Kris Jamsa Wygraj Z C lekcja12
Kris Jamsa Wygraj Z C lekcja28
Kris Jamsa Wygraj Z C lekcja 6
więcej podobnych podstron