DATOTEKE - FAJLOVI

Fajlovi se koriste za privremeno i trajno čuvanje i razmenu podataka. U zavisnosti od vrste informacije koja se smešta u fajl razlikuju se formati fajlova. Format fajla predstavlja način organizacije podataka u fajlu. Poznavanje formata je neophodno da bi aplikacija mogla formirati valjan fajl, koji će kasnije neka druga aplikacija pročitati.

Postoje dve osnovne vrste datoteka:

  • Tekstualne - Čuvaju nizove znakova (štampajućih i upravljačkih), na kraju svakog reda se nalazi '\n', a na kraju kompletnog sadržaja znak EOF. Imaju preglediv sadržaj.
  • Binarne - čuvaju nizove binarnih cifara (0 i 1) bez ikakvih oznaka. Nepreglediv sadržaj, ali je kraćizapis za istu količinu podataka u odnosu na tekstualne datoteke.


Po organizaciji, datoteke mogu biti:

  • sekvencijalne - pristup zapisima je moguć samo po redosledu po kojem su smešteni u memoriji. Ovak način pristipanja naziva se sekvencijalni pristup.
  • relativne - moguće je pristupiti zapisima po proizvoljnom redosledu, na osnovu rednog broja zapisa u datoteci. Ovaj način pristupanja naziva se direktni pristup.
  • indeksne - pristup zapisima na osnovu sadržaja dela zapisa - pristup pomoću ključa.


U jeziku C postoje samo sekvencijalne datoteke koje su po strukturi niz bajtova bez ikakve finije podele. Zato se za njih u literaturi koristi termin "tok" (engl.stream).

U jeziku C postoji rudimentarni oblik direktnog pristupa podacima, koji se svodi na mogućnost pozicioniranja na određeni bajt unutar datoteke. Posle toga se čitanje ili pisanje vrši sekvencijalno, počev od tog bajta.

Pri radu sa datotekama postoje sledeće radnje:

  • otvaranje datoteke
  • pristup datoteci
  • ispitivanje stanja datoteke i
  • zatvaranje datoteke.

Otvaranje datoteke služi za uspostavljanje veze programa sa fizičkom datotekom, na osnovu imena datoteke. Tada se u memoriji stvara određena struktura podataka, koja omogućava efikasan pristup datoteci u toku rada. Ta struktura sadrži i određene podatke o trenutnom stanju datoteke (na primer, trenutnu poziciju pristupa u dototeci).

Pristupom datoteci ostvaruje se prenos podataka u datoteku (upisivanje), ili iz datoteke (čitanje), sa ili bez konverzije u toku prenosa.

Ispitivanjem stanja datoteke, mogu da se dobiju informacije o eventualnim greškama koje su nastale u toku prenosa.

Zatvaranje datoteke je završne radnja, kojom se raskida veza programa sa fizičkom datotekom. Tom prilikom poništavaju se strukture podataka koje su stvorene prilikom otvaranja datoteke.


U daljem izlaganju će biti dat pregled standardnih bibliotečkih funkcija, kojima se u jeziku C ostvaruju operacije vezane za rad sa datotekama. Prototipovi svih tih funkcija nalaze se u standardnom zaglavlju <stdio.h>.


Otvaranje i zatvaranje datoteka

Pokazivač na datoteku

Za svaku datoteku koja se koristi u programu treba da postoji pokazivač na podatak tipa FILE. Taj tip podataka je definisan u <stdio.h> ! Pokazivač datoteke može da se definiše naredbom:

FILE * dat;

U jeziku C postoje tri, unapred definisana, globalna identifikatora (promenljive) tipa FILE *, koji predstavljaju tri standardne tekstualne datoteke koje se uvek automatsku otvaraju na početku izvršavanja programa. Ti identifikatori, odnosno datoteke, su:

stdin - glavni (standardni) ulaz. Predstavlja tastaturu, dok se u komandi operativnog sistema za izvršavanje programa ne kaže drugačije, skretanjem glavnog ulaza

stdout - glavni (standardni) izlaz. Predstavlja ekran, dok se u komandi operativnog sistema za izvršavanje programa ne kaže drugačije, skretanjem glavnog izlaza.

stderr - (standardni) izlaz za poruke o greškama. Uvek predstavlja ekran i ne može da se skreće na neku datoteku. Predviđen je za slanje poruka, obično o greškama, koje uvek moraju da se ispisuju na ekranu, nezavisno od toga gde se ispisuju "obični" podaci.

Primer: Definisanje pokazivača datoteke:

FILE *podaci;


UKRATKO:

Za korišćenje fajlova prvo je potrebno uključiti u aplikaciju zaglavlje “stdio.h”. U ovom zaglavlju se nalaze strukture podataka i funkcije koje se koriste za rad sa fajlovima. Osnovna struktura koja sadrži podatke o fajlu je FILE.

U svakom programu je neophodno imati deklaraciju pokazivača na datoteku:

FILE *pok_dat;

Korišćenjem ovog pokazivača ostvaruje se pristup datoteci.


Otvaranje datoteke

Svaka datoteka koja se u programu koristi (bilo za čitanje ili za upis) mora da se otvori pre nego što joj se prvi put pristupi.

Otvaranje datoteke vrši se pomoću funkcije fopen, čiji je prototip (deklaracija):

FILE *fopen(char* ime_datoteke, char* rezim)

ime_datoteke – string iliti znakovni niz koji sadrži ime datoteke. Ime se zadaje sa relativnim putem u odnosu na radni direktorijum ili sa apsoulutnim putem do mesta gde je datoteka na disku zapisana. Naziv datoteke se piše po pravilima operativnog sistema koji se koristi. Naziv datoteke, pored imena sa proširenjem, po potrebi može da u sebi uključuje i oznaku ulazno-izlaznog uređaja na kojem se nalazi datoteka, i/ili naziv kataloga (foldera ) na uređaju u kojem se nalazi datoteka. U prevodu - Ime se zadaje sa relativnim putem u odnosu na radni direktorijum ili sa apsoulutnim putem do mesta gde je datoteka na disku zapisana. Podrazumevaju se uređaj i katalog u kojima se nalazi program koji se izvršava.

rezim – takođe string koji pokazuje dozvoljeni način pristupa datoteci. Osnovni režimi su:

  • čitanje iz postojeće datoteke ( “r” - read ),
  • upisivanje u novu datoteku (“w” - write - ako datoteka postoji dolazi do brisanja njenog sadržaja prilikom otvaranja, a ako ne postoji, kreira se)
  • dopisivanje na kraju postojeće ili nove datoteke (“a” - append )

Da bi ažuriranje sadržaja datoteke bilo moguće, tj. naizmenično čitanje i pisanje, prethodnim oznakama treba dodati znak +, nezavisno koji je osnovni režim rada. Na taj način se dobijaju oznake:

  • “r+” - čitanje i upis
  • “w+”- upis i čitanje - ako datoteka postoji, briše se njen sadržaj prilikom otvaranja,
  • “a+” - upis i čitanje - pri otvaranju, pokazivač datoteke se postavlja na kraj datoteke.

Ako se datoteka koja ne postoji otvara za pisanje ili dodavanje na kraj, ona se stvara ako je to moguće.

Otvaranje postojeće datoteke za pisanje dovodi do brisanja starog sadržaja, dok otvaranje takve datoteke za dodavanje na kraj čuva prethodni sadržaj.

Pokušaj čitanja datoteke koja ne postoji predstavlja grešku, a mogu postojati i drugi uzroci greške, npr. pokušaj čitanja datoteke za koju nemate dozvolu.

Dok se drugačije ne kaže, podrazumeva se rad sa tekstualnim datotekama.

ANSI standard pravi razliku između tekstualnih i binarnih datoteka, pa uz oznaku režima treba dodati ‘b’ ukoliko se radi sa binarnom datotekom.

Funkcija fopen vraća pokazivač na datoteku koja je otvorena, ili NULL ako datoteka nije mogla da bude otvorena. Vrednost koji funkcija vraća treba dodeliti nekoj pokazivačkoj promenljivoj. Tu promenljivu treba koristiti pri svakom pristupanju datoteci.

Dve tipične greške su sintaksna greška u nazivu datoteke, ili nepostojanje datoteke u  režimu "r". Posebno se skreće pažnja, da u slučaju otvaranja u režimu "w", ako datoteka sa navedenim nazivom već postoji, postojeća datoteka će biti uništena bez opomene i počeće stvaranje nove, prazne datoteke.

Primer - Otvaranje datoteke:

greska = (podaci = fopen("knjiga.txt", "r")) == NULL;

Primer 2:

FILE *pok_dat;
pok_dat = fopen("dat.txt","r");

ili:

if ( ( pok_dat = fopen("dat.txt","r") ) == NULL )
printf(“
dat.txt nije korektno otvorena\n”);

Zatvaranje datoteke

Zatvaranje datoteke vrši se funkcijom fclose, čiji je prototip (deklaracija):

int fclose(FILE   *pok_datoteke)

Ovom funkcijom se prekida veza koja postoji između pokazivača datoteke i imena datoteke. (pok_datoteke je pokazivač datoteke koji je pridružen datoteci koja se zatvara.) Pre zatvaranja sadržaj prihvatne memorije se upisuje u datoteku ukoliko je upis u datoteku dozvoljen.

Ukoliko je zatvaranje izvršeno uspešno, povratna vrednost ove funkcije je 0, a u slučaju greške EOF.

Završetak programa bi trebalo da dovede do automatskog zatvaranja svih otvorenih datoteka.

Primer: zatvaranje datoteke:

greska = fclose ( podaci ) == EOF;


Rad sa tekstualnom datotekom nakon što se ona otvori

U nastavku su date funkcije koje se koriste za rad sa tekstualnim fajlovima, a u zagradi nakom njih je data odgovarajuća funkcija koja bi se koristila ako se koriste glavni ulaz - tastatura i glavni izlaz - ekran)


Standardna funkcija za čitanje jednog znaka (bajta) iz datoteke

int  fgetc( FILE  *pokdat)

Ako se pre učitavanja znaka došlo do kraja datoteke rezultat funkcije je EOF (simbolička konstanta koja označava kraj datoteke (-1) ). Ova konstanta je, takođe, definisana u fajlu stdio.h.

(  int getchar(void);  /* čita 1 znak sa tastature, a ne iz fajla ! */  )


Funkcije za upis jednog znaka (bajta) u datoteku

int   fputc(char c, FILE  *pok_dat)

Rezultat funkcije je upisani znak.

(  int putchar(char c);  /* ispisuje 1 znak na ekran, a ne u fajl ! */  )

Funkcija za čitanje jednog reda iz tekstualne datoteke

char *fgets(char *s, int maxbr, FILE *pok_dat)

Učitava jedan red (niz znakova do znaka ‘\n’) iz datoteke na koju ukazuje pok_dat.

s je niz u koji se smešta učitani red, a maxbr-1 je maksimalni broj znakova koji se mogu učitati.

(  char * gets(char * s);  /* čita 1 red znakova sa tastature, do kraja reda */  )

Funkcija za upis jednog reda u tekstualnu datoteku

int fputs(char *s, FILE *pok_dat)

(  int puts(char * s);  /* ispisuje 1 red znakova na ekran, a ne u fajl ! */  )

Funkcija za formatirano čitanje podataka iz tekstualne datoteke

int fscanf(FILE *pok_dat,char *format [,arg]…)

( int scanf ( char * format, arg1, arg2, ...);    /* čita sa tastature */  )

Funkcija služi za čitanje podataka iz fajla na koji ukazuje pok_dat. Povratnu vrednost predstavlja broj podataka koje je funkcija učitala u argumente. Ako se pojavi greška pri učitavanju povratna vrednost je -1.

Parametri:

1. pok_dat – pokazivač na fajl iz koga treba učitavati podatke.

2. format – predstavlja niz karaktera koji označava način konverzije (niza karaktera u podatak odgovarajućeg tipa) koji treba primeniti pri učitavanju podataka iz fajla u promenljive zadate kao parametri argument (npr. “%d”). Ovaj parametar odgovara prvom parametru funkcije scanf().

3. argument – predstavlja promenljivu u koju treba učitati vrednost. Tip ovog argumenta mora odgovarati tipu konverziji naznačenom u parametru format.

Može postojati više parametara argument, s tim da broj argumenata ovog tipa treba da odgovara broju specifikacija konverzija u formatu da ne bi došlo do greške.

Primer:

char znak, rec[20]; 
int povratna, brojCeo;
double brojRealan;
FILE
*pokFajla;
pokFajla =
fopen( “Dokument.txt”, “r” );
...
povratna = fscanf( pokFajla, “%c %s %d %f”, znak, rec, brojCeo, brojRealan );
...

povratna =
fclose(pokFajla );


Funkcija za formatirani upis podataka u tekstualne datoteke

int fprintf(FILE *pok_dat,char *format [,arg]…)

( int printf ( char * format, arg1, arg2, ...);  /* piše na ekran /*  )

Funkcija služi za upisivanje podataka u fajl na koji ukazuje pok_dat. Povratna vrednost predstavlja broj podataka koje je funkcija upisala u fajl. Ako se pojavi greška pri učitavanju povratna vrednost je -1.

Parametri:

1. pok_dat – pokazivač na fajl iz kojeg treba učitavati podatke.

2. format – predstavlja niz karaktera koji označava način konverzije (podatka odgovarajućeg tipa u niz karaktera) koji treba primeniti pri upisu podataka u fajl iz promenljivih koje su navedene kao parametri argument (npr. “%d”). Ovaj parametar odgovara prvom parametru funkcije printf().

3. argument – predstavlja promenljivu čiju vrednost treba upisati u fajl. Tip ovog argumenta mora odgovarati tipu konverziji naznačenom u parametru format. Može postojati više parametara argument, s tim da broj argumenata ovog tipa treba da odgovara broju specifikacija konverzija u formatu da ne bi došlo do greške.


Primer:

char znak, rec[20]; 
int povratna, brojCeo;
double brojRealan;
FILE
*pokFajla1, *pokFajla2;

pokFajla1 =
fopen(“Dokument1.txt”, “r” );
pokFajla2 =
fopen(“Dokument2.txt”, “r” );
...

povratna =
fscanf(pokFajla1,“%c %s %d %f”, znak, rec, brojCeo, brojRealan );
...

povratna =
fprintf(pokFajla2,“%c %s %d %f”, znak, rec, brojCeo, brojRealan );
...

povratna =
fclose(pokFajla1 );
povratna =
fclose(pokFajla2 );


DODATNO - ovo nismo stigli da radimo na času:

Funkcije za direktan pristup

Da bi se direktno pristupilo nekom podatku u okviru datoteke, mora se znati njegovo rastojanje u bajtovima od početka datoteke, kraja datoteke ili od tekuće pozicije.

Standardna funkcija za pozicioniranje u datoteci


int fseek(FILE *pok_dat, long n, int reper)

pok_dat - ukazuje na datoteku u kojoj se vrši pozicioniranje,

n - broj bajtova za koliko se pomera datotečni pokazivač u odnosu na zadatu lokaciju,

reper - definiše u odnosu na koju lokaciju se vrši pomeranje:

reper=0, pomeranje se vrši u odnosu na početak datoteke,

reper=1, pomeranje se vrši u odnosu na tekuću poziciju,

reper=2, pomeranje se vrši u odnosu na kraj datoteke.


Funkcija za nalaženje trenutne vrednosti datotečnog pokazivača

long int ftell (pok_dat)

Daje trenutnu poziciju pokazivača datoteke (tj. broj bajtova od početka datoteke do trenutne pozicije)


Funkcija za ispitivanje da li je datotečni pokazivač pozicioniran na kraj datoteke

int feof(FILE *dat_pok);

Vraća vrednost različitu od nule ukoliko je datotečni pokazivač pozicioniran na kraj datoteke.


Funkcija za pozicioniranje na početak datoteke

void rewind(FILE *pok_dat)


Last modified: Wednesday, 3 April 2019, 1:30 AM