PLIKI:
Plikiem (ang. file) w najprostszym rozumieniu jest ciąg danych tego samego typu składowanych w pamięci zewnętrznej komputera. Przykładem „ciągu danych” może być zestaw liczb, linii tekstu, struktur itd.
Każdy plik identyfikowany jest przez nazwę.
Predefiniowany typ danych o nazwie FILE umożliwiający deklarowanie zmiennych plikowych.
Deklaracja:
FILE *plik;
powoduje zarezerwowanie przez kompilator pewnego bufora roboczego w pamięci operacyjnej komputera oraz wykreowanie wskaźnika plik wskazującego początek tego bufora.
(Plik tworzony jest w pamięci jako wskaźnik struktury pliku.)
Funkcje ułatwiające posługiwanie się plikami:
1. Otwarcie pliku
FILE *fopen(const char *path, const char *mode);
path - nazwa pliku,
mode - parametr określający specyfikę współpracy z podanym plikiem
Wartości parametru mode:
r - plik otwarty do czytania
w - nowy plik jest otwarty tylko do zapisywania
a - plik otwarty do dopisywania
r+ - istniejący plik otwarty do czytania i zapisywania
w+ - nowy plik otwarty do zapisywania i czytania
a+ - istniejący plik zostaje otwarty do dopisywania i czytania
Rodzaje plików:
tekstowy - t
binarny - b
Parametr mode np. rt, rb itd.
2. Zamknięcie pliku
int fclose(FILE *plik);
3. Zamknięcie wszystkich otwartych plików
int fcloseall(void);
Przykład:
#include <stdio.h>
FILE *plik; /*deklaracja zmiennej plikowej*/
...
/*otwarcie pliku*/
plik=fopen(”c:\\BORLANDC\\PROGRAMY\\dane.txt”,”r+”);
...
/*zamknięcie pliku*/
fclose(plik);
Funkcje wprowadzania i wyprowadzania danych:
zapisanie danych do pliku znak po znaku putc() lub fputc()
odczytywanie danych z pliku znak po znaku getc() lub fgetc()
zapisywanie danych do pliku łańcuchami fputs()
odczytywanie danych z pliku łańcuchami fgets()
zapisywanie blokami do pliku fwrite()
odczytywanie blokami z pliku fread()
zapisywanie sformatowanych danych do pliku fprintf()
odczytywanie sformatowanych danych z pliku fscanf()
Przykład putc i fgetc
#include <stdio.h>
#include <process.h>
main()
{
FILE *plik_we;
char nazwa[80];
int znak;
printf(”\n Wyswietlanie zawartosci pliku tekstowego \n”);
printf(”\n Podaj nazwe pliku:”);
gets(nazwa);
plik_we=fopen(nazwa,”r”);
if(plik_we==NULL)
{
printf(”\nPlik %s nie istnieje”,nazwa);
exit(1);
}
else
{
while((znak=fgetc(plik_we))!=EOF)
fputc(znak,stdout);
fclose(plik_we);
}
}
Funkcja exit służy do zamknięci wszystkich nie zamkniętych plików i zakończenia wykonywania programu.
int fgetc(FILE *plik); - odczytuje znak z plik, zwraca wartość znaku lub EOF
int fputc (int c, FILE *plik); - wysyła c do plik, zwraca c lub EOF
Nazwy plików standardowych w języku C:
stdin - standardowy plik wejściowy
stdout - standardowy plik wyjściowy
stderr - standardowy plik błędów
stdaux - standardowy plik pomocniczy
stdprn - standardowy plik drukarki
Czytanie z pliku i zapis do pliku łańcuchów
char *fgets(char *s, int n, FILE *plik);
Funkcja odczytuje znaki ze strumienia plik i umieszcza je w łańcuchu s. Odczyt zostaje przerwany po odczytaniu n-1 znaków lub końca wiersza. Funkcja umieszcza na końcu łańcucha s znak \0. Wartością funkcji jest s lub NULL.
Odczyt po 20 znaków z pliku i wyświetlenie na ekran:
FILE *plik;
char lancuch[80];
...
while(fgets(lancuch, 20, plik)!=NULL)
printf(lancuch);
Wskaźnik końca pliku przy wczytywaniu wiersza = NULL, a nie EOF jak przy wczytywaniu znaków.
int fputs(const char *s, FILE *plik);
Funkcja wysyła łańcuch s do strumienia plik. Nie dołącza końca wiersza, natomiast znak końca łańcucha nie zostaje wysłany. Wartością funkcji jest liczba nieujemna lub EOF.
Zapis łańcucha do pliku:
FILE *plik;
char lancuch[80];
....
puts(” Podaj lancuch”);
gets(lancuch);
fputs(lancuch, plik);
fputs(”\n”, plik);
Czytanie z pliku i zapis do pliku blokami
int fread (void *wsk, int rozmiar_bloku, int liczba_blokow, FILE *plik);
wsk - wskaźnik początku obszaru pamięci operacyjnej
rozmiar_bloku - wielkość bloku w bajtach
liczba_blokow - ilość wczytywanych bloków
plik - wskaźnik pliku, z którego czytamy
double tab[10];
FILE *plik;
fread(tab, sizeof(double), 10, plik);
struct ksiazka
{
char nazwisko[30];
char tytul[40];
float cena;
int num_kat;
} k1;
fread(&k1,sizeof(k1), 1, plik);
Funkcja fread zwraca liczbę faktycznie odczytanych elementów.
int fwrite(void *wsk, int rozmiar_bloku, int liczba_blokow, FILE *plik);
wsk - wskaźnik początku obszaru pamięci operacyjnej
rozmiar_bloku - wielkość bloku w bajtach
liczba_blokow - ilość zapisywanych bloków
plik - wskaźnik pliku, do którego zapisujemy
double tab[10];
FILE *plik;
fwrite(tab, sizeof(double), 10, plik);
struct ksiazka
{
char nazwisko[30];
char tytul[40];
float cena;
int num_kat;
} k1;
fwrite(&k1,sizeof(k1), 1, plik);
Funkcja fwrite zwraca liczbę wszystkich wysłanych elementów.
Sformatowane wejście - wyjście:
Zapis do pliku:
int fprintf(FILE *plik, format, ...);
wartość int równa liczbie wyprowadzanych znaków lub EOF (w przypadku błędu)
plik - wskaźnik do pliku
format - format zapisywanych wartości
... - lista zapisywanych zmiennych
struct ksiazka
{
char nazwisko[30];
char tytul[40];
float cena;
int num_kat;
} k1;
do
{
printf(”Podaj nazwisko i imie autora: ”);
gets(k1.nazwisko);
printf(”Podaj tytul: ”);
gets(k1.tytul);
printf(”Podaj cene ksiazki: ”);
scanf(”%f”,&k1.cena);
printf(”Podaj numer katalogowy: ”);
scanf(”%d”,&k1.num_kat);
fprintf(plik, ”%s%s%f%d”,k1.nazwisko, k1.tytul, k1.cena, k1.num_kat);
} while (strlen(k1.nazwisko)>0);
Odczyt z pliku:
int fscanf(FILE *plik, format, ...);
wartość int liczba prawidłowo odczytanych danych lub EOF (jeśli koniec zbioru)
plik - wskaźnik do pliku
format - format odczytywanych wartości
... - lista odczytywanych zmiennych
struct ksiazka
{
char nazwisko[30];
char tytul[40];
float cena;
int num_kat;
} k1;
while(fscanf(plik, ”%s%s%f%d”,k1.nazwisko, k1.tytul, &k1.cena, &k1.num_kat) !=EOF)
{
printf(”Nazwisko i imie autora: %s \n”,k1.nazwisko);
printf(”Tytul: %s \n”,k1.tytul);
printf(”Cene ksiazki: %f \n”,k1.cena);
printf(”Numer katalogowy: %d \n”,k1.num_kat);
}
lub
while (!feof(plik))
{
fscanf(plik, ”%s%s%f%d”,k1.nazwisko, k1.tytul, &k1.cena, &k1.num_kat);
printf(”Nazwisko i imie autora: %s \n”,k1.nazwisko);
printf(”Tytul: %s \n”,k1.tytul);
printf(”Cene ksiazki: %f \n”,k1.cena);
printf(”Numer katalogowy: %d \n”,k1.num_kat);
}
Funkcja feof - bada koniec pliku
int feof (FILE *plik)
funkcja zwraca wartość 0 jeśli nie osiągnięto końca zbioru.
Funkcja fflush - wysyła zawartość buforu do pliku określonego przez wskaźnik (opróżnienie bufora)
int fflush(FILE *plik);
Funkcja fflushall - funkcja wysyła zawartość wszystkich buforów otwartych strumieni wyjściowych do związanych z nimi plików oraz kasuje zawartość buforów strumieni wejściowych.
int fflushall(void);
Funkcja unlink - usunięcie pliku o określonej nazwie
int unlink (char * nazwa_pliku);
np. unlink(”plik_pom.tmp”);
Wartość zwraca przez funkcję:
0 - poprawne wykonanie
-1 - błąd
Funkcja remove - usunięcie pliku o określonej nazwie
int remove(char * nazwa_pliku);
np. remove(”plik_pom.tmp”);
Wartość zwraca przez funkcję:
0 - poprawne wykonanie
-1 - błąd
Funkcja rename - zmienia nazwę pliku
int rename(char *stara_nazwa, char *nowa_nazwa);
np. rename(”plik_pom.tmp”, ” plik_bib.c”);
Funkcje do przetwarzania swobodnego
funkcja rewind - ustawia wskaźnik pliku na pozycję początkową
void rewind(FILE *plik);
funkcja fseek - ustawia wskaźnik pliku na wybraną pozycję
int fseek(FILE *plik, long pozycja, int odniesienie);
pozycja - określa liczbę bajtów od miejsca określonego przez parametr odniesienie.
odniesienie - określa trzy możliwe położenia wskaźnika pliku:
SEEK_SET - początek pliku
SEEK_CUR - pozycja bieżąca
SEEK_END - koniec pliku
Rezultatem funkcji fseek jest dana typu int o wartości 0, jeżeli funkcja ma przebieg pomyślny, lub różną od 0, gdy wykonanie funkcji było niepomyślne.
Odczytanie i-tej pozycji tablicy z pliku
poz=(long) i*sizeof(double);
fseek (plik, poz, SEEK_SET);
fread (&wartosc, sizeof(double), 1, plik);
funkcja ftell wyznacza liczbę bajtów oddzielającą pozycję bieżącą wskaźnika pliku od początku pliku
long ftell(FILE *plik);
Chcąc poznać rozmiar pliku, trzeba wykonać dwie instrukcje:
fseek(plik, 0, SEEK_END);
rozmiar=ftell(plik);