Temat: Operacje na plikach. Pliki tekstowe i binarne. Faza otwarcia
Transkrypt
Temat: Operacje na plikach. Pliki tekstowe i binarne. Faza otwarcia
J.Koszelew Temat: Operacje na plikach. Pliki tekstowe i binarne. Faza otwarcia, zapisu/odczytu i zamkni cia pliku. 1. Rodzaje plików W j zyku C/C++ wyró niamy dwa rodzaje plików: • pliki binarne • pliki tekstowe Plik binarny to ci g bajtów zapami tanych w pami ci zewn trznej (dyskowej). Zapis i odczyt pliku binarnego jest zrealizowany w postaci porcji bajtów, a nast pnie porcja ta mo e by zinterpretowana jako okre lony typ danych. Elementem jednostkowym pliku binarnego jest jeden bajt. Format pliku binarnego: [bajty pliku] [EOF] EOF – znak ko ca pliku (end of file) Plik tekstowy to tak e ci g bajtów zapami tanych w pami ci zewn trznej (dyskowej). Jednak bajty te mog by zinterpretowane jedynie jako pojedy cze znaki albo ła cuchy. 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 ko ca linii w pliku stdio.h – plik udost pniaj cy funkcje realizuj ce operacje na plikach binarnych i tekstowych 1 J.Koszelew Do reprezentowania plików w programach słu plikowymi (w skrócie strumienie). zmienne zwane strumieniami Przykład 1 FILE ∗plik_wej, ∗wyniki ; // definicja zmiennych „strumieniowych” Strumienie reprezentowane s przez zmienne typu FILE. Typ FILE to struktura zawieraj ca informacje o cie ce do pliku, trybie otwarcia, itp. Wszystkie operacje na strumieniu wymagaj podania wska nika na t struktur . 2. Fazy pracy z plikiem • Otwarcie pliku • Zapis lub odczyt • Zamkni cie pliku a) Otwarcie pliku W fazie otwarcia pliku okre lamy: cie k do pliku oraz tryb otwarcia. Faza otwarcia pliku jest realizowana przez wywołanie funkcji fopen FILE ∗ fopen ( char ∗nazwa_pliku, char ∗tryb_otwarcia ) mo liwe tryby otwarcia: r − w − a − + − b − t − tylko do odczytu tylko do zapisu (utworzenie nowego) dopisywanie na ko cu z mo liwo ci aktualizacji otwarcie jako plik binarny otwarcie jako plik tekstowy Funkcja fopen zwraca adres NULL, gdy nie dojdzie do otwarcia strumienia 2 J.Koszelew Przykład 2 FILE ∗plik; // utworzenie pliku binarnego z mo liwo ci 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) Zamkni cie pliku int fclose ( FILE ∗strumien ) // zamkni cie wskazanego strumienia int fcloseall (void ) // zamkni cie wszystkich strumieni c) Zapis danych do strumienia Pliki tekstowe int fputc ( int znak, FILE ∗strumien ) // zapis pojedynczego znaku int fputs ( char ∗tekst, FILE ∗strumien ) // zapis ła cucha znaków int fprintf ( FILE ∗strumien, char ∗format, . . . ) // funkcja sformatowanego wyj cia analogiczna do printf Pliki binarne int fwrite ( void∗ adres_w_pamieci, size_t rozmiar_bloku, size_t ilosc_blokow, FILE ∗ strumien) // funkcja kopiuj ca (ilosc_blokow∗rozmiar_bloku) bajtów // spod wskazanego obszaru pami ci do strumienia (pliku) Przykład 3 // zapis danych z tablicy struktur do pliku binarnego – wersja I #include <stdio.h> struct student { char nazwisko[31]; char imie[16]; 3 J.Koszelew int wiek; }; 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 #include <stdio.h> 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 zrealizowane poprawnie, je eli rozmiar bloku sizeof(student)*10 nie przekroczy maksymalnego rozmiaru bloku, który mo e jednorazowo zapisa funkcja fwrite. 4 J.Koszelew Przykład 5 // zapis danych z tablicy struktur do pliku tekstowego #include <stdio.h> 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 ła cucha składaj cego si z co najwy ej (dlugosc−1) znaków int fscanf ( FILE ∗strumien, char ∗format, . . . ) // funkcja sformatowanego wej cia analogiczna do scanf Pliki binarne int fread ( void∗ adres_w_pamieci, size_t rozmiar_bloku, size_t ilosc_blokow, FILE ∗ strumien) // funkcja odczytuj ca (ilosc_blokow∗rozmiar_bloku) bajtów // ze strumienia do wskazanego obszaru pami ci 5 J.Koszelew Przykład 6 // odczyt struktur z pliku binarnego i wstawienie ich do tablicy struktur #include <stdio.h> 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 danych z pliku tekstowego i wstawienie ich do tablicy struktur #include <stdio.h> 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++; 6 J.Koszelew } fclose( strumien ); } return 0; } 3. Funkcje pomocnicze int int feof ( FILE ∗strumien ) // testowanie osi gni cia ko ca pliku fseek ( FILE ∗strumien, long przesuniecie, int wzgledem) long ftell // przesuwa wska nik pliku o zadan ilo bajtów // wzgl dem zadanego miejsca: SEEK_SET - wzgl dem pocz tku pliku SEEK_CUR - wzgl dem aktualnej pozycji SEEK_END - wzgl dem ko ca pliku ( FILE ∗strumien ) // zwraca aktualn pozycj wska nika pliku Przykład 8 // odczyt pliku liczb całkowitych od ko ca 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 J.Koszelew Przykład 9 // program realizuj cy przetwarzanie danych w tablicy struktur oraz zapis // i odczyt danych w pliku #include <stdio.h> #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; } 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) { 8 J.Koszelew 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-znajdz osobe\n"); printf("3-policz bogaczy\n"); printf("4-zapisz dane\n"); printf("5-wczytaj dane\n"); printf("6-drukuj w pliku\n"); printf("7-koniec programu\n"); scanf("%d",&z); return z; } 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; 9 J.Koszelew *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); } 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);break; case 2:printf("Podaj nazwisko osoby szukanej: "); scanf("%s",naz); 10 J.Koszelew szukaj(T,ile,naz); break; case 3:printf("Podaj wysokosc sredniej krajowej: "); scanf("%f",&zar); printf("Liczba osob zarabiajacych powyzej sredniej: %d\n",policz_bogaczy(T,ile,zar)); break; case 4:printf("Podaj sciezke pliku do zapisu: "); scanf("%s",sciezka); zapis(sciezka,T,ile); break; case 5:printf("Podaj sciezke pliku do odczytu: "); scanf("%s",sciezka); odczyt(sciezka,T,&ile); break; case 6:printf("Podaj sciezke pliku tekstowego: "); scanf("%s",sciezka); zapis_do_tekstowego(sciezka,T,ile); } }while (z!=7); return 0; } 11