Programowanie Procedurale. Pliki w jezyku C++

Transkrypt

Programowanie Procedurale. Pliki w jezyku C++
Programowanie Procedurale.
Pliki w jezyku
˛
C++
Bożena Woźna-Szcześniak
[email protected]
Jan Długosz University, Poland
Wykład 10
Bożena Woźna-Szcześniak (AJD)
Programowanie Procedurale. Pliki w jezyku
˛
C++
Wykład 10
1 / 22
Co to jest plik i do czego służy?
Plik to dokument lub inny zbiór danych zapisany na dysku lub
innym nośniku, oznaczony unikatowa˛ nazwa.
˛
Plik jest ciagiem
˛
bajtów i ma określony poczatek
˛
i koniec.
Dane w pliku ułożone sa˛ jedna po drugiej.
Odczyt pliku realizowany jest tak jak odczyt z kasety
magnetofonowej (odtworzenie pewnego fragmentu powoduje
przewiniecie
˛
kasety), a tym samym ponowne odtworzenie
spowoduje przeczytanie/odtworzenie nowego fragmentu.
Aby odczytać pewien fragment pliku nalezy najpierw ustawić
wskaźnik aktualnego położenia na poczatek
˛
fragmentu, który
chcemy przeczytać/zapisać a nastepnie
˛
odczytać (read) lub
zapisać (write) dane, które nas interesuja.
˛
Bożena Woźna-Szcześniak (AJD)
Programowanie Procedurale. Pliki w jezyku
˛
C++
Wykład 10
2 / 22
Strumienie
Strumienie (ang. stream) zapewniaja˛ przepływ danych z
programu do pliku lub odwrotnie.
Strumień nie jest zwiazany
˛
z konkretnym urzadzeniem.
˛
Aby przeprowadzić operacje˛ wejścia/wyjścia, należy
skojarzyć plik ze strumieniem.
Istnieja˛ dwa formaty strumieni: tekstowy oraz binarny
Biblioteka standardowa C++ w kwestii operacji wejścia/wyjścia
składa sie˛ z dwóch rzeczy:
Jedna to jest biblioteka fstream (ifstream, ofstream i
iostream).
Druga to biblioteka odziedziczona z C, dostepna
˛
przez plik
nagłówkowy <cstdio>.
Bożena Woźna-Szcześniak (AJD)
Programowanie Procedurale. Pliki w jezyku
˛
C++
Wykład 10
3 / 22
Pliki tekstowe a pliki binarne
Brak różnicy dla tekstu, ale istnieja˛ istotne różnice w formie
przechowywania liczb.
W plikach binarnych położenie kolejnej danej określane jest na
podstawie rozmiaru poprzedniej.
W plikach tekstowych dane rozdzielone sa˛ znakami, przecinkami,
średnikami, spacjami, tabulatorami itp.
Bożena Woźna-Szcześniak (AJD)
Programowanie Procedurale. Pliki w jezyku
˛
C++
Wykład 10
4 / 22
Dostep
˛ do pliku
Trzy kroki które musza˛ zostać wykonane przy dostepie
˛
do pliku:
1. Otworzyć plik
2. Odczyt lub/i zapis
3. Zamknać
˛ plik
Przy tradycyjnym sposobie obsługi plików krok 1 i 3 sa˛ takie same
niezależnie od tego czy mamy do czynienia z plikiem tektowym
czy binarnym.
Bożena Woźna-Szcześniak (AJD)
Programowanie Procedurale. Pliki w jezyku
˛
C++
Wykład 10
5 / 22
Otwarcie pliku - fopen
Zadeklarować wskaźnik do pliku typu FILE – handler
Struktura FILE służy do zarzadzania
˛
plikami i jest zdefiniowana w
pliku <cstdio>.
Wskaźnik typu FILE służy do odwoływania sie˛ do konkretnego
pliku dyskowego.
W obrebie
˛
struktury FILE można znaleźć: rozmiar pliku, znacznik
pozycji w pliku , adres bufora danych itp.
Wywołać funkcje˛ fopen(). Funkcja ta przekazuje wskaźnik do
otwartego strumienia pliku.
Przykład: FILE * strumien = fopen ( "Plik.txt",
"wt") ;
Bożena Woźna-Szcześniak (AJD)
Programowanie Procedurale. Pliki w jezyku
˛
C++
Wykład 10
6 / 22
fopen (char const* path, char const*
mode);
path - nazwa pliku wraz z ewentualna˛ ścieźka˛ dostepu.
˛
Nazwa ta
może zostać podana bezpośrednio lub przez zmienna˛
przechowujac
˛ a˛ tablice˛ znaków.
Jeśli operacja otwarcia pliku nie powiedzie sie,
˛ to funkcja zwraca
wskaźnik pusty (null pointer).
mode - tryby otwarcia pliku:
wt lub w- otwarcie pliku ASCII do zapisu (plik jest tworzony od
nowa),
rt lub r - otwarcie pliku ASCII do odczytu,
at lub a- otwarcie pliku ASCII do dołaczenia
˛
(zapisu na końcu pliku)
wb, rb, ab - jak wyżej tylko dla plików binarnych
Bożena Woźna-Szcześniak (AJD)
Programowanie Procedurale. Pliki w jezyku
˛
C++
Wykład 10
7 / 22
fopen (char const* path, char const*
mode);
mode - tryby otwarcia pliku:
r+t, r+b - otwarcie pliku do zapisu i odczytu (wskaźnik jest
ustawiany na poczatku
˛
pliku).
w+t, w+b - plik jest tworzony od nowa (jeśli istnieje to jest
czyszczony i otwierany do odczytu i zapisu).
a+t, a+b - tak samo jak dla r+ z tym, że wskaźnik ustawiany jest
na końcu.
Bożena Woźna-Szcześniak (AJD)
Programowanie Procedurale. Pliki w jezyku
˛
C++
Wykład 10
8 / 22
Dostep
˛ do pliku binarnego
Zapis/odczyt realizowany jest za pomoca˛ funkcji fwrite, fread.
Funkcje dokonuja˛ zapisu/odczytu wyspecyfikowanej ilości bajtów
poczawszy
˛
od aktualnej pozycji w strumieniu.
Funkcie fread i fwrite maja˛ taka˛ sama liste˛ argumentów:
fwrite(void * buffer, long size, long count,
FILE * stream );
buffer - adres poczatku
˛
pamieci
˛ spod której kopiowane/zapisywane
bed
˛ a˛ dane
size - rozmiar pojedynczego bloku pamieci
˛ (elementu)
count - ilość elementów do skopiowania
stream - wskaźnik do strumienia pliku
Bożena Woźna-Szcześniak (AJD)
Programowanie Procedurale. Pliki w jezyku
˛
C++
Wykład 10
9 / 22
Przemieszczanie w pliku
Aktualne położenie w pliku:
FILE * strumien = fopen ("Plik.bin", "w+b");
int pos = ftell ( strumien ) ;
Przesuniecie połozenia w strumieniu do pozycji wzgledem
˛
poczatku,
˛
aktualnej pozycji lub końca strumienia:
fseek ( strumien , offset , seek_dir ) ; gdzie
seek_dir może wynosić:
SEEK_SET - położenie wzgledem
˛
poczatku
˛
pliku
SEEK_CURR - położenie wzgledem
˛
aktualnego położenia
SEEK_END - położenie wzgledem
˛
końca pliku
Przykład: fseek ( strumien ,100 ,SEEK_SET ) ;
Przykład: fseek ( strumien , 0L , SEEK_SET );
równoważne rewind(strumien);
Bożena Woźna-Szcześniak (AJD)
Programowanie Procedurale. Pliki w jezyku
˛
C++
Wykład 10
10 / 22
Przykład
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int main() {
FILE * strumien = fopen ("Plik.bin", "w+b");
if (strumien) { cout << "Udalo sie otworzyc plik " << endl;}
else {cout << "Nie udalo sie otworzyc pliku "<< endl;}
int zmienna1 = 5;
long zmienna2 = 8;
long zmienna3 = 0xCCCCCC;
int tab []={10,16,8,1} ;
char napis [] = "zwykly t e k s t";
fwrite (&zmienna1 , sizeof (int) ,1 , strumien ) ;
fwrite (&zmienna2 , sizeof (long) ,1 , strumien ) ;
fwrite (&zmienna3 , sizeof (long) ,1 , strumien ) ;
fwrite (&tab , sizeof (int) ,4 , strumien ) ;
fwrite (napis , sizeof (char) , strlen (napis) , strumien ) ;
...
Bożena Woźna-Szcześniak (AJD)
Programowanie Procedurale. Pliki w jezyku
˛
C++
Wykład 10
11 / 22
Przykład
...
rewind(strumien);
int a; fread (&a, sizeof (int) ,1 , strumien ) ;
long b, c;
fread (&b , sizeof (long) ,1 , strumien ) ;
fread (&c , sizeof (long) ,1 , strumien ) ;
cout << a << " " << b << " " << hex << c << dec << endl;
int *s = new int [4];
fread (s , sizeof (int) ,4 , strumien ) ;
for (int i = 0; i< 4 ; i++) cout<< s[i] << " ";
cout << endl;
char *s2 = new char [strlen(napis)+1];
fread (s2 , sizeof (char) ,strlen(napis) , strumien ) ;
for (int i = 0; i< strlen(napis) ; i++) cout<< s2[i] << " ";
cout << endl;
fclose (strumien) ;
return 0;
}
Bożena Woźna-Szcześniak (AJD)
Programowanie Procedurale. Pliki w jezyku
˛
C++
Wykład 10
12 / 22
Obsługa plików tekstowych - zapis
Do obsługi plików stosuje sie˛ funkcje analogiczne jak printf i
scanf, z tym, że zawieraja˛ one wskaźnik do strumienia, z którego
dane bed
˛ a˛ odczytywane czy też zapisywane.
Bożena Woźna-Szcześniak (AJD)
Programowanie Procedurale. Pliki w jezyku
˛
C++
Wykład 10
13 / 22
Przykład
#include <cstdio>
#include <iostream>
using namespace std;
int main() {
FILE * strumien = fopen ("Plik.txt", "w+t");
if (strumien) { cout << "Udalo sie otworzyc plik " << endl;}
else {cout << "Nie udalo sie otworzyc pliku "<< endl;}
int z1 = 5;
long z2 = 8;
long z3 = 0xCCCCCC;
int tab []={10, 16, 8, 1} ;
char napis [] = "zwykly t e k s t";
//printf ( "%d , %ld , %ld , %s ",z1,z2,z3,napis) ;
cout << z1 << " " << z2 << " " << hex << z3 << dec
<< " " << napis << endl;
fprintf (strumien,"%d , %ld , %ld , %s " ,z1,z2,z3,napis) ;
fclose (strumien) ;
return 0;
}
Bożena Woźna-Szcześniak (AJD)
Programowanie Procedurale. Pliki w jezyku
˛
C++
Wykład 10
14 / 22
Obsługa plików tekstowych - zapis
Funkcje printf() i fprintf() umożliwiaja˛ ustawienie
minimalnej szerokości pola oraz precyzji (ilości miejsc po
przecinku) w wyświetlaniu liczb zmiennoprzecinkowych:
float liczba =1.5673892;
printf ( "%f ", liczba ) ;
// wyświetla liczbe z domyślnymi ustawieniami
printf("%f10.3 n ", liczba );
printf("%f10.4 n ", liczba );
// wyświetla liczbe na polu 10 znakowym z dokładnościa˛ do 3
miejsc po przecinku
Bożena Woźna-Szcześniak (AJD)
Programowanie Procedurale. Pliki w jezyku
˛
C++
Wykład 10
15 / 22
Przykład
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int main () {
FILE * pFile = fopen ("myfile.txt","w");
char name [100];
for (int n=0 ; n<3 ; n++) {
cout << "please, enter a name: ";
fgets (name,100,stdin);
name[strlen(name)-1]=’\0’;
fprintf (pFile, "Name %d [%-10.10s]\n",n,name);
}
fclose (pFile);
return 0;
}
Bożena Woźna-Szcześniak (AJD)
Programowanie Procedurale. Pliki w jezyku
˛
C++
Wykład 10
16 / 22
Odczyt danych z pliku tekstowego
Załóżmy że mamy nastepuj
˛ acy
˛ plik:
1,1.1
2,14.3
6,12.8
zawiera on w każdej linii dwie liczby: całkowita˛ oraz
zmiennoprzecinkowa.
˛
Do wyświetlenia pojedynczej linii na ekranie służy wiec
˛ wzorzec:
"%d,%f"
Ten sam wzorzec stosuje sie˛ do odczytu przy wykorzystaniu
funkcji fscanf().
int fscanf ( FILE * stream, const char * format,
... );
Bożena Woźna-Szcześniak (AJD)
Programowanie Procedurale. Pliki w jezyku
˛
C++
Wykład 10
17 / 22
Przykład
#include <cstdio>
int main () {
char str [80]; float f;
FILE * pFile = fopen ("myfile.txt","w+");
fprintf (pFile, "%f %s", 3.1416, "PI");
rewind (pFile);
fscanf (pFile, "%f", &f);
fscanf (pFile, "%s", str);
fclose (pFile);
printf ("I have read: %f and %s \n",f,str);
return 0;
}
Bożena Woźna-Szcześniak (AJD)
Programowanie Procedurale. Pliki w jezyku
˛
C++
Wykład 10
18 / 22
Przykład
#include <cstdio>
int main()
{
int c;
while ((c = getc(stdin)) != EOF) {
putc(c, stdout);
}
return 0;
}
Bożena Woźna-Szcześniak (AJD)
Programowanie Procedurale. Pliki w jezyku
˛
C++
Wykład 10
19 / 22
Przykład
#include <iostream>
using namespace std;
int main()
{
int c;
c = cin.get();
while (!cin.eof()) {
cout << (char)c;
c = cin.get();
}
return 0;
}
Bożena Woźna-Szcześniak (AJD)
Programowanie Procedurale. Pliki w jezyku
˛
C++
Wykład 10
20 / 22
Przykład
#include <iostream>
#include <cstdio>
using namespace std;
int main(int argc, char *argv[]) {
int ch; FILE* fp;
long long counter = 0;
if (argc != 2) {
cout <<"Sposób użycia: "<< argv[0] << "nazwaPliku\n";
return 1;
}
if ((fp = fopen(argv[1], "r")) == NULL) {
cout<<"Nie można otworzyć pliku o nazwie "<<argv[1]<<endl;
return 1;
}
while ((ch = getc(fp)) != EOF) ++counter;
fclose(fp);
cout << "Ilość znaków w pliku o nazwie: "
<< argv[1] <<" " << counter << endl;
return 0;
}
Bożena Woźna-Szcześniak (AJD)
Programowanie Procedurale. Pliki w jezyku
˛
C++
Wykład 10
21 / 22
Przykład
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char *argv[]) {
char ch; fstream is; long long counter = 0;
if (argc != 2) {
cout <<"Sposób użycia: "<< argv[0] << "nazwaPliku\n";
return 1; }
is.open (argv[1]);
if (!is.is_open()) {
cout<<"Nie można otworzyć pliku o nazwie: "<<argv[1]<< endl;
return 1; }
while (is.good()) {
ch = is.get(); // get character from file
if (is.good()) ++counter;
}
is.close();
cout<<"Ilość znaków w pliku: "<<argv[1]<<" = "<<counter<<endl;
return 0;
}
Bożena Woźna-Szcześniak (AJD)
Programowanie Procedurale. Pliki w jezyku
˛
C++
Wykład 10
22 / 22