Programowanie Proceduralne Pliki Bożena Woźna-Szcześniak bwozna@gmail.com Jan Długosz University, Poland Wykład 12
Operacje plikowe Plik - dokument lub inny zbiór danych zapisany na dysku, oznaczony unikatowa nazwa. Plik jest ciagiem bajtów Plik w C: plik dyskowy (disk file) urzadzenie peryferyjne typu terminal drukarka
Strumień Strumień (stream) w C: przepływ danych z programu do pliku lub odwrotnie Strumień nie jest zwiazany z konkretnym urzadzeniem (device-independend) Aby przeprowadzić operację Wejścia/Wyjścia, należy skojarzyć plik ze strumieniem Dwa formaty strumieni: text or binary stream
Buforowanie Wejścia/Wyjścia Bufor - obszar pamięci służacy do tymczasowego przechowywania danych przed przesłaniem ich do miejsca przeznaczenia Posługujac się buforami system operacyjny zmniejsza ilość odwołań do fizycznych urzadzeń Wejścia/Wyjścia Strumienie We/Wy sa buforowane w sposób domyślny Fizyczny zapis do pliku - buffer flush
Wskaźniki typu FILE Struktura FILE służy do zarzadzania plikami i jest zdefiniowana w pliku stdio.h Wskaźnik typu FILE służy do odwoływania się do konkretnego pliku dyskowego. W obrębie struktury FILE można znaleźć: rozmiar pliku, znacznik pozycji w pliku, adres bufora danych itp.
Otwieranie pliku FILE* fopen (char const* path, char const* mode); Jeśli operacja otwarcia pliku nie powiedzie się, to funkcja zwraca wskaźnik pusty (null pointer). Nazwy plików sa ograniczone do FILENAME_MAX znaków. Jednocześnie można otworzyć co najwyżej FOPEN_MAX plików. Powyższe dwie wartości zdefiniowana sa w zbiorze stdio_lim.h Dla gcc version 4.1.2 20061027 wartość FILENAME_MAX = 4096, natomiast FOPEN_MAX=16
Tryby otwarcia pliku mode Znaczenie Pozycja r Otwarcie pliku tekstowego do odczytu Poczatek r+ Otwarcie pliku do odczytu i zapisu Poczatek Usunięcie zawartości pliku lub w utworzenie nowego pliku do zapisu Poczatek Otwarcie do odczytu i zapisu w+ Jeśli plik istnieje, jego zawartość zostaje usunięta Poczatek Otwarcie do dopisywania a Jeśli plik nie istnieje, zostaje utworzony Koniec Otwarcie do odczytu i zapisu a+ Jeśli plik nie istnieje, zostaje utworzony Koniec
Otwieranie/zamykanie pliku FILE *fptr; if ((fptr = fopen( TEST.TXT, r )) == NULL){ printf( Nie moge otworzyc pliku TEST.TXT.\n); exit(1); } Po wykonaniu operacji plik należy odłaczyć od strumienia danych: int fclose(file* stream); Funkcja fclose() wykonuje czyszczenie bufora. Przykład: zliczanie bajtów w pliku program countbytes.c
Odczyt i zapis plików fgetc() i fputc() znak-po-znaku getc() i putc() równoważne fgetc i fputc. Definiowane zazwyczaj jako makro. getc(stdin) równoważne int getchar(void) int fgetc(file *stream); int fputc(int c, FILE *stream); fgets() i fputs() wiersz-po-wierszu char* fgets(char *s, int n, FILE *stream); int fputs(const char *s, FILE *stream); fread() i fwrite() blok-po-bloku size_t fread(void *ptr, size_t size, size_t n, FILE *str); size_t fwrite(const void *ptr, size_t size, size_t n, FILE *str);
Odczyt i zapis plików Przykłady Kopiowanie plików tekstowych program textcopy.c Kopiowanie dowolnych plików program bincopy.c Problem z otwieraniem pliku przy stosowaniu funkcji fgets do wczytywania nazwy pliku program bad.c Rozwi azanie problemu z otwieraniem pliku przy stosowaniu funkcji fgets do wczytywania nazwy pliku program good.c
Funkcje do obsługi plików (stdio.h) int fseek(file* stream, long offset, int origin); Funkcja wyznacza pozycję w strumieniu stream; następne czytanie lub pisanie będzie odnosić się do danych rozpoczynjacych się od nowej pozycji. Dla plków binarnych nowa pozycja wypada w miejscu oddalonym o offset znaków od punktu odniesienia origin, który może mieć wartości SEEK_SET (poczatek pliku), SEEK_CUR (bieżaca pozycja w pliku), SEEK_END (koniec pliku). Dla plików tekstowych wartość offset musi być równa zeru lub wartości zwróconej przez funkcje ftell(); UWAGA! Pod linuxem plik binarny i tekstowy sa traktowane tak samo. Funkcja zwraca wartość różna od zera w przypadku błędu.
Funkcje do obsługi plików (stdio.h) Przykładowe programy Wypisywanie pliku w odwrotnej kolejności program reverse.c Odczytywanie wielkości pliku w bajtach program filesize.c
Funkcje do obsługi plików (stdio.h) long ftell(file* stream); Funkcja zwraca wartość bieżacej pozycji dla strumienia stream lub -1L w przypadku niepowodzenia. Przyklad: program filesize.c. void rewind(file* stream); Wywolanie rewind(fp) jest równoważne z ciagiem wywolań: fseek(fp,0l,seek_set); clearerr(fp); Przyklad: programy filesize.c, student.
Funkcje do obsługi plików (stdio.h) int fgetpos(file* stream, fpos_t *ptr); Funkcja zapamietuje bieżac a pozycje strumienia stream w miejscu wskazywanym przez ptr. W przypadku błędu funkcja zwraca wartość różna od zera. int fsetpos(file* stream, const fpos_t *ptr); Funkcja ustawia bieżac a pozycje strumienia stream według wartości zapamietanej przez funkcję fgetpos() w miejscu wskazywanym przez ptr. W przypadku błędu funkcja zwraca wartość różna od zera. Przykład: program fsize.c
Funkcje do obsługi plików (stdio.h) int remove(const char* path); Funkcja usuwa wskazany plik tak, że późniejsza próba otworzenia go zakończy się niepowodzeniem. Funkcja zwraca wartość różna od zera jeśli usunięcie pliku się nie powiedzie; Przyklad: program remove_test.c. int rename(const char* oldname,const char* newname); Funkcja zmienia nazwe pliku z oldname na newname. Funkcja zwraca wartość różna od zera jeśli zamiana się nie powiedzie; Przyklad: program rename_test.c.
Funkcje do obsługi plików (stdio.h) FILE* freopen (char const* filename, char const* mode, FILE* stream); Funkcja freopen otwiera wskazany plik (filename) przy wskazanym rodzaju dostępu (mode) i wiaże z nim strumień stream. Funkcja zwraca wartość stream lub NULL w przypadku błędu. Funkcji freopen zwykle używa się do zmiany plików zwiazanych ze strumieniami stdin, stdout i stderr. Przyklad: program freopen_test.c.
Funkcje do obsługi plików (stdio.h) #include <stdio.h> int main(void) { int c; FILE *p=fopen("good.c","r"); if (p!=null){ while ((c = getc(p))!= EOF) putc(c, stdout); } FILE *r=freopen("good.c","r",p); if(r!=null){ printf("udalo sie zmienic p na r\n"); while ((c = getc(r))!= EOF) putc(c,stdout); } fseek(r,0l,seek_set); FILE *ekran=freopen("telewizor","w",stdout); if(ekran!=null){ printf("udalo sie zmienic na ekran\n"); while ((c = getc(r))!= EOF) putc(c,ekran); } fclose(r); fclose(ekran); return 0; }
Funkcje do obsługi plików (stdio.h) FILE* tmpfile(void) - otwiera plik tymczasowy w trybie w+. Znika, gdy zostaje zamknięty, lub gdy kończy się program. int access(const char* path, int amode) - sprawdza istnienie pliku w systemie. Znajduje sie w zbiorze unistd.h. Parametr amode może przyjać wartość R_OK, W_OK, X_OK (tryby zapisu), lub F_OK (test istnienia). Funkcja zwraca wartość 0 w przypadku istnienia pliku i możliwości dostępu do niego. W przeciwnym przypadku zwraca wartość -1 i ustawia stosownie zmienna errno.
Funkcje do obsługi błędów (stdio.h) int feof(file* stream); Funkcja zwraca wartość różna od zera w przypadku, gdy jest ustawiony znacznik końca pliku dla strumienia stream. int clearerr(file* stream); Funkcja kasuje znaczniki końca pliku i błedu dla strumienia stream. int ferror(file* stream); Funkcja zwraca wartość różna od zera w przypadku, gdy jest ustawiony znacznik błędu dla strumienia stream.
Funkcje do obsługi błędów (stdio.h) void perror(const char* s); Wywolanie perror(s) wypisuje tekst z tablicy s i zalezny od implementacji komunikat o błędzie odpowiadający wartości errno (zdefiniowanej w zbiorze errno.h). Przykład: przetwarzanie plików, ktorych nazwy podawane sa jako argumenty programu szkielet programu openclose.c