Temat: Operacje na plikach. Pliki tekstowe i binarne. Faza otwarcia, zapisu/odczytu i zamknicia pliku. 1. Rodzaje plików W jzyku C/C++ wyróniamy dwa rodzaje plików: pliki binarne pliki tekstowe Plik binarny to cig bajtów zapamitanych w pamici zewntrznej (dyskowej). Zapis i odczyt pliku binarnego jest zrealizowany w postaci porcji bajtów, a nastpnie porcja ta moe by zinterpretowana jako okrelony typ danych. Elementem jednostkowym pliku binarnego jest jeden bajt. Format pliku binarnego: [bajty pliku] [EOF] EOF znak koca pliku (end of file) Plik tekstowy to take cig bajtów zapamitanych w pamici zewntrznej (dyskowej). Jednak bajty te mog by zinterpretowane jedynie jako pojedycze znaki albo łacuchy. Elementem jednostkowym pliku tekstowego jest znak. Format pliku tekstowego: [znaki 1 linii pliku] [/r ] [/n] [znaki 2 linii pliku] [/r] [/n]... [znaki ostatniej linii pliku][eof] /r znak powrotu karetki /n znak koca linii w pliku stdio.h plik udostpniajcy funkcje realizujce operacje na plikach binarnych i tekstowych 1
Do reprezentowania plików w programach słu zmienne zwane strumieniami plikowymi (w skrócie strumieniami). Przykład 1 FILE plik_wej, wyniki ; // definicja zmiennych strumieniowych Strumienie reprezentowane s przez zmienne typu FILE. Typ FILE to struktura zawierajca informacje o ciece do pliku, trybie otwarcia, itp. Wszystkie operacje na strumieniu wymagaj podania wskanika na t struktur. 2. Fazy pracy z plikiem Otwarcie pliku Zapis lub odczyt Zamknicie pliku a) Otwarcie pliku W fazie otwarcia pliku okrelamy: ciek do pliku oraz tryb otwarcia. Faza otwarcia pliku jest realizowana w funkcji fopen FILE fopen ( char nazwa_pliku, char tryb_otwarcia ) tryb otwarcia: r tylko do odczytu w tylko do zapisu (utworzenie nowego) a dopisywanie na kocu + z moliwoci aktualizacji b otwarcie jako plik binarny t otwarcie jako plik tekstowy Funkcja fopen zwraca adres NULL, gdy nie dojdzie do otwarcia strumienia 2
Przykład 2 FILE plik; // utworzenie pliku binarnego z moliwoscia aktualizacji plik = fopen( a:\\wyniki.dat, w+b ); if( plik == NULL ) // kontrola błdów we/wy printf( Blad otwarcia pliku wyników ); else... b) Zamknicie pliku int fclose ( FILE strumien ) int fcloseall (void ) // zamknicie wskazanego strumienia // zamknicie wszystkich strumieni c) Zapis danych do strumienia Przykład 3 Pliki tekstowe int fputc ( int znak, FILE strumien ) // zapis pojedynczego znaku int fputs ( char tekst, FILE strumien ) // zapis łacucha znaków int fprintf ( FILE strumien, char format,... ) // funkcja sformatowanego wyjscia analogiczna do printf Pliki binarne int fwrite ( void adres_w_pamieci, size_t rozmiar_bloku, size_t ilosc_blokow, FILE strumien) // funkcja kopiujca (ilosc_blokow rozmiar_bloku) bajtów // spod wskazanego obszaru pamici do strumienia (pliku) // zapis danych z tablicy struktur do pliku binarnego wersja I struct student char nazwisko[31]; char imie[16]; int wiek; ; 3
main( ) FILE *strumien; student T[10]; if ( (strumien = fopen( "dane.dat", " wb " ) )!= NULL ) for (int i=0;i<10;i++) fwrite( &T[i], sizeof(student), 1, strumien); fclose( strumien ); return 0; Przykład 4 // zapis danych z tablicy struktur do pliku binarnego wersja II struct student char nazwisko[31]; char imie[16]; int wiek; ; main( ) FILE *strumien; student T[10]; if ( (strumien = fopen( "dane.dat", " wb " ) )!= NULL ) fwrite( T, sizeof(student), 10, strumien); fclose( strumien ); return 0; Uwaga!!! Wywołanie fwrite(t, sizeof(student), 10, strumien) zostanie zrealizowne poprawnie, jeeli rozmiar bloku sizeof(student)*10 nie przekroczy maksymalnego rozmiaru bloku, który moe jednorazowo zapisa funkcja fwrite. 4
Przykład 5 // zapis danych z tablicy struktur do pliku tekstowego struct student char nazwisko[31]; char imie[16]; int wiek; ; main( ) FILE *strumien; student T[10]; if ( (strumien = fopen( "dane.txt", " wt " ) )!= NULL ) for( int i = 0; i < 10; i++ ) fprintf ( strumien, %s %s %d \n, T[ i ].nazwisko, T[ i ].imie, T[ i ].wiek ); fclose( strumien ); d) Odczyt danych ze strumienia Pliki tekstowe int fgetc ( FILE strumien ) // wczytanie pojedynczego znaku char fgets ( char tekst, int dlugosc, FILE strumien ) // wczytanie łacucha składajcego si z co najwyej (dlugosc 1) znaków int fscanf ( FILE strumien, char format,... ) // funkcja sformatowanego wejcia analogiczna do scanf Pliki binarne int fread ( void adres_w_pamieci, size_t rozmiar_bloku, size_t ilosc_blokow, FILE strumien) // funkcja odczytujca (ilosc_blokow rozmiar_bloku) bajtów // ze strumienia do wskazanego obszaru pamici 5
Przykład 6 // odczyt struktur z pliku binarnego i wstawienie ich do tablicy struktur struct student char nazwisko[31]; imie[16]; int wiek; ; main( ) FILE *strumien; student T[10]; int ilosc_osob; if ( (strumien = fopen( "dane.dat", " rb " ) )!= NULL ) ilosc = 0; while( fread( &T[ilosc], sizeof(student), 1, strumien) == 1) ilosc++; fclose( strumien ); return 0; Przykład 7 // odczyt struktur z pliku tekstowego i wstawienie ich do tablicy struktur struct student char nazwisko[31]; char imie[16]; int wiek; ; main( ) FILE *strumien; student T[10]; int ilosc_osob=0; if ( (strumien = fopen( "test.txt", " rt " ) )!= NULL ) for( int i = 0; (! feof(strumien) ) && (i < 10); i++ ) fscanf( strumien, %s %s %d,t[ i ].nazwisko, T[ i ].imie, &(T[ i].wiek); ilosc_osob++; fclose( strumien ); return 0; 6
3. Funkcje pomocnicze int feof ( FILE strumien ) // testowanie osignicia koca pliku int fseek ( FILE strumien, long przesuniecie, int wzgledem) // przesuwa wskanik pliku o zadan ilo bajtów // wzgldem zadanego miejsca: SEEK_SET - wzgldem pocztku pliku SEEK_CUR - wzgldem aktualnej pozycji SEEK_END - wzgldem koca pliku long ftell ( FILE strumien ) // zwraca aktualn pozycj wskanika pliku Przykład 8 // odczyt pliku liczb całkowitych od koca main() FILE *f; f=fopen("dane.dat","wb"); for (int i=0;i<5;i++) fwrite(&i,sizeof(int),1,f); fclose(f); f=fopen("dane.dat","rb"); fseek(f,-sizeof(int),seek_end); int i=1,liczba; while (ftell(f)!=0) fread(&liczba,sizeof(int),1,f); printf("%d ",liczba); i++; fseek(f,-sizeof(int)*i,seek_end); fread(&liczba,sizeof(int),1,f); printf("%d ",liczba); fclose(f); 7
Przykład 9 // program z wykładu nr 8 uzupełniony o operacje na plikach #include <conio.h> #include <string.h> struct Osoba char nazwisko[40]; unsigned wiek; float zarobki; ; void dodaj_osobe(osoba *T,int *ile) int i=*ile; printf("nazwisko:"); scanf("%s",t[i].nazwisko); printf("wiek:"); scanf("%d",&t[i].wiek); printf("zarobki:"); scanf("%f",&t[i].zarobki); i++; *ile=i; short usun_osobe(osoba *T,int *ile,char *naz) short byla=0; for (int i=0;i<*ile;i++) if (strcmp(t[i].nazwisko,naz)==0) byla=1; for (int j=i;j<*ile;j++) T[j]=T[j+1]; (*ile)--; return byla; 8
void wypisz_informacje(osoba O) printf("nazwisko:%s\nwiek:%d\nzarobki:%0.2f\n",o.nazwisko, O.wiek,O.zarobki); void szukaj(osoba *T, int ile,char *naz) int byla=0; for (int i=0;i<ile;i++) if (strcmp(t[i].nazwisko,naz)==0) wypisz_informacje(t[i]); byla=1; if (byla==0) printf("brak osoby o nazwisku %s \n",naz); int policz_bogaczy(osoba *T, int ile, float zar) int l=0; for (int i=0; i<ile; i++) if (T[i].zarobki>zar) l++; return l; #define n 100 int menu() int z; printf("1-dodaj osobe\n"); printf("2-usun osobe\n"); printf("3-znajdz osobe\n"); printf("4-policz bogaczy\n"); printf("5-zapisz dane\n"); printf("6-wczytaj dane\n"); printf("7-drukuj w pliku\n"); printf("8-koniec programu\n"); scanf("%d",&z); return z; 9
void zapis(char *sciezka,osoba *T,int ile) FILE *f; f=fopen(sciezka,"wb"); if (f!=null) for (int i=0;i<ile;i++) fwrite(&t[i],sizeof(osoba),1,f); fclose(f); void odczyt(char *sciezka,osoba *T,int *ile) FILE *f; *ile=0; f=fopen(sciezka,"rb"); if (f!=null) while (fread(&t[*ile],sizeof(osoba),1,f)==1) (*ile)++; fclose(f); void zapis_do_tekstowego(char *sciezka,osoba *T,int ile) FILE *f; f=fopen(sciezka,"wt"); if (f!=null) for (int i=0;i<ile;i++) if (i==0) fprintf(f,"lista osob\n"); fprintf(f,"%40s %3d %10.2f\n",T[i].nazwisko,T[i].wiek,T[i].zarobki); fclose(f); 10
int main( ) Osoba T[n]; char naz[40]; int ile=0,z,byla; float zar; char sciezka[100]; do z=menu(); switch(z) case 1: dodaj_osobe(t,&ile); case 2: printf("podaj nazwisko do usuniecia:"); scanf("%s",naz); byla=usun_osobe(t,&ile,naz); if (!byla) printf ("Brak takiej osoby!!!"); case 3:printf("Podaj nazwisko osoby szukanej: "); scanf("%s",naz); szukaj(t,ile,naz); case 4:printf("Podaj wysokosc sredniej krajowej: "); scanf("%f",&zar); printf("liczba osob zarabiajacych powyzej sredniej: %d\n",policz_bogaczy(t,ile,zar)); case 5:printf("Podaj sciezke pliku do zapisu: "); scanf("%s",sciezka); zapis(sciezka,t,ile); case 6:printf("Podaj sciezke pliku do odczytu: "); scanf("%s",sciezka); odczyt(sciezka,t,&ile); case 7:printf("Podaj sciezke pliku tekstowego: "); scanf("%s",sciezka); zapis_do_tekstowego(sciezka,t,ile); while (z!=8); return 0; 11