Przechowywanie danych czyli
pliki w j ˛ezyku C++
mgr in˙z. Piotr Kaczmarek
Piotr.Kaczmarek@put.poznan.pl
Politechnika Pozna´nska, Instytut Automatyki i In˙zynierii Informatycznej
Przechowywanie danych czyli pliki w j˛ezyku C++ – p. 1/46
Plik a kaseta magnetofonowa
Plik słu˙zy do przechowywania danych na dysku lub innym no´sniku.
Ma okre´slony pocz ˛atek i koniec Dane uło˙zone s ˛a jedna po drugiej
Odczyt pliku realizowany jest tak jak odczyt kasety magnetofonowej (odtworzenie pewnego fragmentu powoduje przewini ˛ecie kasety) a tym samym
ponowne odtworzenie spowoduje
Plik a kaseta magnetofonowa cd...
W pliku, w odró˙znieniu od tablicy zapisuj ˛ac dane nie okre´sla si ˛e ich poło˙zenia (zostan ˛a one po prostu
dograne). W operacjach zapisu/odczytu okre´sla si ˛e wył ˛acznie ilo´s´c danych do zapisu/ odczytu
Aby odczyta´c pewien fragment pliku nale˙zy najpierw ustawi´c marker aktualnego poło˙zenia na pocz ˛atek fragmentu który chcemy przeczyta´c/zapisa´c a
nast ˛epnie odczyta´c (read) lub zapisa´c (write) dane które nas interesuj ˛a.
Przechowywanie danych czyli pliki w j˛ezyku C++ – p. 3/46
Pliki tekstowe vs binarne
Brak ró˙znicy dla tekstu
istniej ˛a istotne ró˙znice w formie przechowywania liczb zale˙zne od sposobu kodowania
W plikach binarnych poło˙zenie kolejnej danej
okre´slane jest na podstawie rozmiaru poprzedniej W plikach tekstowych dane rozdzielone s ˛a znakami przecinkami, ´srednikami, spacjami, tabulatorami itp.
Reprezentacja liczb w pliku tekstowym
Przechowa´c liczby: 12345,128,12346 1 = 49 = 0x31 (w ASCII)
2 = 50 = 0x32 (w ASCII) ...
, = 44 = 0x2C (w ASCII) ...
Przechowywanie danych czyli pliki w j˛ezyku C++ – p. 5/46
Reprezentacja liczb w pliku binarnym
Przechowa´c liczby: 12345,128,12346 12345 = 0x3039
128 = 0x0080 12346 = 0x303A
Dost ˛ep do pliku
Trzy kroki które musz ˛a zosta´c wykonane przy dost ˛epie do pliku:
1. Otworzy´c plik
2. Odczyt lub/i zapis 3. Zamkn ˛a´c plik
Przy tradycyjnym sposobie obsługi plików krok 1 i 3 s ˛a takie same niezale˙znie od tego czy mamy do
czynienia z plikiem tektowym czy binarnym
Przechowywanie danych czyli pliki w j˛ezyku C++ – p. 7/46
Otwarcie pliku - fopen
1. Zadeklarowa´c wska´znik do pliku handler
2. Wywoła´c funkcj ˛e fopen() Funkcja przekazuje wska´znik do otwartego strumienia pliku.
Przykład:
FILE ∗s t r u m i e n ;
s t r u m i e n = fopen ( “ P l i k . t x t ” , ” w t ” ) ;
Otwieranie pliku - argumenty (1)
fopen(arg1, arg2
arg1- Nazwa pliku zawieraj ˛aca nazw ˛e i ew. ´scie˙zk˛e dost ˛epu: “c:\\ mojkatalog\\ Plik.txt”. Nazwa ta mo˙ze zosta´c podana bezpo´srednio lub przez zmienn ˛a
przechowuj ˛ac ˛a tablic ˛e znaków np tt char[.]
Przechowywanie danych czyli pliki w j˛ezyku C++ – p. 9/46
Otwieranie pliku - argumenty (2)
fopen(arg1, arg2)
arg2 - tryb dost ˛epu:
wt Otwarcie pliku ASCII do zapisu (plik jest tworzony od nowa),
rt Otwarcie pliku ASCII do odczytu,
at Otwarcie pliku ASCII do doł ˛aczenia (zapisu na ko ´ncu pliku)
wb, rb, ab Jak wy˙zej tylko dla plików binarnych
Otwieranie pliku - argumenty (3)
Ponadto
r+t, r+b otwarcie pliku do zapisu i odczytu (strumie ´n jest ustawiany na pocz ˛atku pliku
w+t, w+b plik jest tworzony od nowa (je´sli istnieje to czyszczony i otwierany do odczytu i zapisu
a+t, a+b Tak samo jak dla r+ z tym, ˙ze strumie ´n ustawiany jest na ko ´ncu
Przechowywanie danych czyli pliki w j˛ezyku C++ – p. 11/46
Dost ˛ep do pliku binarnego
Zapis/odczyt realizowany jest za pomoc ˛a funkcji fwrite,fread. Funkcje dokonuj ˛a zapisu/odczytu
wyspecyfikowanej ilo´sci bajtów pocz ˛awszy od aktualnej pozycji w strumieniu.
Funkcie fread i fwrite maj ˛a tak ˛a sama list ˛e argumentów:
fwrite(void * buffer, long size, long count, FILE * stream );
buffer - adres pocz ˛atku pami ˛eci spod której kopiowane/zapisywane b ˛ed ˛a dane
Dost ˛ep do pliku binarnego
Przykład:
FILE ∗s t r u m i e n ;
s t r u m i e n = fopen ( “ P l i k _ b i n . b i n ” , ”w+ b ” ) ; i n t zmienna1 = 5 ;
long zmienna2 = 8 ;
long zmienna3=0xCCCCCC;
i n t t a b [ ] = { 1 0 , 1 6 , 8 , 1 } ;
char n a p i s [ ] = " z w y k l y t e k s t " ;
f w r i t e (& zmienna1 , s i z e o f ( i n t ) , 1 , s t r u m i e n ) ; f w r i t e (& zmienna2 , s i z e o f ( long ) , 1 , s t r u m i e n ) ; f w r i t e (& zmienna3 , s i z e o f ( long ) , 1 , s t r u m i e n ) ;
f w r i t e (& tab , s i z e o f ( i n t ) , 4 , s t r u m i e n ) ; / / z a p i s t a b l i c y f w r i t e ( napis , s i z e o f ( char ) , s t r l e n ( n a p i s ) , s t r u m i e n ) ; f c l o s e ( s t r u m i e n ) ;
Przechowywanie danych czyli pliki w j˛ezyku C++ – p. 13/46
Przemieszczanie w pliku
Aktualne połozenie w pliku:
FILE ∗s t r u m i e n ;
s t r u m i e n = fopen ( “ P l i k _ b i n . b i n ” , ”w+ b ” ) ; i n t pos= f t e l l ( s t r u m i e n ) ;
przesuniecie połozenia w strumieniu do pozycji wzgl ˛edem pocz ˛atku, aktualnej pozycji lub ko ´nca strumienia:
Przemieszczanie w pliku
gdzie seek dir mo˙ze wynosi´c:
SEEK_SET - poło˙zenie wzgl ˛edem pocz ˛atku pliku SEEK_CURR - poło˙zenie wzgl ˛edem aktualnego poło˙zenia
SEEK_END - poło˙zenie wzgl ˛edem ko ´nca pliku
Przechowywanie danych czyli pliki w j˛ezyku C++ – p. 15/46
Obsługa plików tekstowych - zapis
Do obsługi plików stosuje si ˛e funkcje analogiczne jak printf i scanf, z tym, ˙ze zawieraj ˛a one wska´znik do strumienia, z którego dane b ˛ed ˛a odczytywane czy te˙z zapisywane.
FILE ∗s t r u m i e n ;
s t r u m i e n = fopen ( “ P l i k _ t x t . t x t ” , ”w+ t ” ) ; i n t z1 = 5 ;
long z2 = 8 ;
long z3=0xCCCCCC;
char n a p i s [ ] = " z w y k l y t e k s t " ;
p r i n t f ( "%d , %l d , %l d , %s " , z1 , z2 , z3 , n a p i s ) ;
Obsługa plików tekstowych - zapis
Funkcje prinf(.) i fprinf(.) umo˙zliwiaj ˛a
ustawienie minimalnej szeroko´sci pola oraz precyzji (ilo´sci miejsc po przecinku) w wy´swietlaniu liczb
zmiennoprzecinkowych:
f l o a t l i c z b a =1.5673892;
p r i n t f ( "∗%f ∗\ n " , l i c z b a ) ;
/ / w y ´s w i e t l a l i c z b e z domy ´slnymi u s t a w i e n i a m i p r i n t f ( "∗%f 1 0 . 3∗\ n " , l i c z b a ) ;
p r i n t f ( "∗%f 1 0 . 4∗\ n " , l i c z b a ) ;
/ / w y ´s w i e t l a l i c z b ˛e na p o l u 10znakowym
z d o k ł a d n o ´s c i ˛a do 3 m i e j s c po p r z e c i n k u
wynik :
∗1.56738∗
∗ 1.567∗
∗ 1.5673∗ Przechowywanie danych czyli pliki w j˛ezyku C++ – p. 17/46
Odczyt danych z pliku tekstowego (1)
Załó˙zmy ˙ze mamy nast ˛epuj ˛acy plik:
1 , 1 . 1 2 , 1 4 . 3 6 , 1 2 . 8
zawiera on w ka˙zdej linii dwie liczby: całkowit ˛a oraz
zmiennoprzecinkow ˛a. Do wy´swietlenia pojedynczej linii na ekranie słu˙zy wi ˛ec wzorzec:
"%d,%f"
Ten sam wzorzec stosuje si ˛e do odczytu przy
Odczyt danych z pliku tekstowego(2)
FILE ∗s t r u m i e n ; i n t l i c z b a 1 ; f l o a t l i c z b a 2 ;
s t r u m i e n = fopen ( “ D a n e _ t x t . t x t ” , ” r + t ” ) ;
f s c a n f ( s t r u m i e n , " \%d ,\% f " ,& l i c z b a 1 ,& l i c z b a 2 ) ;
\ \ o d c z y t p i e r w s z e j l i n i i
f s c a n f ( s t r u m i e n , " \%d ,\% f " ,& l i c z b a 1 ,& l i c z b a 2 ) ;
\ \ o d c z y t d r u g i e j l i n i i . . .
f c l o s e ( s t r u m i e n ) ;
Przechowywanie danych czyli pliki w j˛ezyku C++ – p. 19/46
Wykorzystanie strumieni (1)
1. Tworzony jest strumie ´n
2. Strumie ´n dowi ˛azywany jest do pliku
3. zapis i odczyt z pliku odbywa si ˛e za pomoc ˛a operatorów «,»
4. strumie ´n jest zamykany
Wykorzystanie strumieni (2)
Dost ˛ep do pliku tekstowego jest równie˙z mo˙zliwy analogicznie jak dla cin i cout.
Dla czytania i zapisu z pliku wykorzystuje si ˛e strumie ´n typu fstream
f s t r e a m s t r u m i e n _ p l i k u ( " nazwa_pliku " , t r y b ) ;
Tryb okre´sla czy plik b ˛edzie otwierany do zapisu i odczytu:
ios::in - otwarcie do odczytu ios::out - otwarcie do zapisu
ios::app - otwarcie do zapisu na koncu istniej ˛acego pliku
ios::in|ios::out - otwarcie do zapisu i odczytu
Przechowywanie danych czyli pliki w j˛ezyku C++ – p. 21/46
Wykorzystanie strumieni (2)
f s t r e a m s t r u m i e n ( " p l i k _ s t r . t x t " , i o s : : o u t ) ; i n t z1 = 5 ;
long z2 = 8 ;
long z3=0xCCCCCC;
char n a p i s [ ] = " z w y k l y t e k s t " ; / / z a p i s
s t r u m i e n <<z1<< " , " <<z2<< " , " <<z3<< " , " << n a p i s ; s t r u m i e n . c l o s e ( ) ; / / zamkniecie s t r u m i e n i a
Wykorzystanie strumieni - manipulatory (1)
Manipulatory umo˙zliwiaj ˛a modyfikowanie sposobu wy´swietlania danych:
Zmiana formatu wyswietlania:
hex - wy´swietlanie liczby w formie szesnastkowej oct - wy´swietlanie liczby w formie ósemkowej
dec - wy´swietlanie liczby w formie dziesi ˛etnej
i n t z1 =193;
s t r u m i e n <<z1<< " , " <<hex<<z1<< " , " << o c t <<z1 ;
Przechowywanie danych czyli pliki w j˛ezyku C++ – p. 23/46
Wykorzystanie strumieni - manipulatory (2)
Precyzja
f l o a t a =10.56789;
s t r u m i e n << s e t p r e c i s i o n (3) < < a ;
/ / u s t a w i a now ˛a p r e c y z j ˛e w y ´s w i e t l a n i a
Szeroko´s´c pola
i n t z1 =67;
s t r u m i e n << ’ ( ’ <<setw (10) < <a<< ’ ) ’ << e n d l ; / / umieszcza a w p o l u 10 znakowym
Pozycja w strumieniu
Aby uzyska´c dost ˛ep do okre´slonej danej znajduj ˛acej si ˛e wewn ˛atrz pliku, bez konieczno´sci czytania wszystkich
elementów poprzedzajacych, nalezy ustawi´c połozenie w strumieniu na miejsce w którym sie ona znajduje:
Uzyskanie informacji o aktualnym połozeniu:
i n t pos= s t r u m i e n . t e l l p ( ) ;
przesuniecie połozenia w strumieniu do pozycji wzgl ˛edem pocz ˛atku strumienia:
s t r u m i e n . seekp ( 1 0 0 ) ;
/ / przesuwa p o z y c j ˛e w s t r u m i e n i u o 100 b a j t ó w od pocz ˛atku p
Przechowywanie danych czyli pliki w j˛ezyku C++ – p. 25/46
Pozycja w strumieniu
przesuniecie połozenia w strumieniu do pozycji wzgl ˛edem pocz ˛atku, aktualnej pozycji lub ko ´nca strumienia:
s t r u m i e n . seekp ( 1 0 0 , s e e k _ d i r ) ;
/ / przesuwa p o z y c j ˛e w s t r u m i e n i u o 100 b a j t ó w od pocz ˛atku , ko ´nca l u b p o z y c j i a k t u a l n e j
gdzie seek dir mo˙ze wynosi´c:
ios::beg - poło˙zenie wzgl ˛edem pocz ˛atku pliku