You are on page 1of 15

ProgramiranjeI_sylabus.

doc

Fakultet informacijskih tehnologija


denis@fit.ba

Datum:29.04.2014
Vjebe 8

Manipulisanje fajlovima (datotekama)


U dosadanjim materijalima smo uglavnom koristili primjere programskog koda koji
nakon izvrenja nisu ostavljali nikakve podatke koje bismo mogli naknadno iskoristiti.
Razlog tome je injenica da su nai podaci bili pohranjeni u privremenoj memoriji, te su
po zavretku programa bili nepovratno izgubljeni. Kako bismo izbjegli gubljenje
podataka, u ovom materijalu emo obraditi neke od naina koji omoguavaju da nae
podatke pohranimo u odgovarajue fajlove, ime se stvaraju mogunosti za njihovo
kasnije koritenje.
U kontekstu fajlova, pohranjivanje podataka se obino vri u tekstualnom ili binarnom
formatu. Tekstualni format podrazumijeva pohranu podataka u obliku koji je razumljiv
ovjeku jer kompletan sadraj fajla (karakteri, brojevi i dr.) predstavlja tekst. S druge
strane, binarni format podrazumijeva pohranu podataka u obliku koji je razumljiv samo
raunaru. Binarni fajlovi mogu sadravati karaktere, cjelobrojne vrijednosti (brojeve),
nizove, objekte i td. Za binarni fajl jednostavno moemo rei da sadri binarnu
prezentaciju naih podataka.
Koji od navedenih formata e se koristiti prvenstveno zavisi od potreba i zahtjeva kojima
naa aplikacija treba odgovoriti. Svaki od pomenutih formata ima svoje prednosti i
nedostatke. Tekstualni format je itljiviji i vjerojatno e, bez veih problema, raditi na
bilo kojem sistemu. S druge strane, poto se ne zahtijeva posebna konverzija, veu
koliinu podataka emo mnogo bre upisati i ispisati u binarnom formatu. Poto postoje
odreene razlike u manipulaciji razliitim formatima fajlova prvo emo govoriti o
tekstualnim fajlovima.

Manipulisanje tekstualnim fajlovima


Rad s fajlovima zahtijeva malo kompleksnije operacije nego to je to sluaj sa
standardnim ulazima i izlazima (cin>> i cout<<). Prije svega, u zavisnosti od toga ta
elimo uraditi, moramo kreirati odgovarajui stream objekat. Kada odreeni sadraj
elimo upisati u fajl tada koristimo objekat klase ofstream, dok za ispis sadraja nekog
fajla koristimo objekat klase ifstream.

O klasama emo govoriti u okviru predmeta Programiranje II, ali za sada termin klasa
moete smatrati sinonimom za rije struktura (strukture smo obradili u jednom od
prethodnih materijala).
Programiranje I:: Vjebe
http://student.fit.ba/

ProgramiranjeI_sylabus.doc

Fakultet informacijskih tehnologija


denis@fit.ba

Da bismo mogli manipulisati fajlovima u na program je potrebno ukljuiti fstream


biblioteku unutar koje se nalaze ifstream i ofstream klase.
#include <fstream>

Ukljuivanjem fstream biblioteke u mogunosti smo kreirati objekte pomenutih klasa.


Takoer, za ilustraciju moemo rei da se objekat klase ifstream ponaa isto kao cin
objekt (upis), dok se objekt klase ofstream ponaa isto kao cout objekat (ispis).
Naravno, objekti tipa ofstream podatke usmjeravaju prema odabranom fajlu, tok objekat
cout podatke usmjerava prema konzoli. U narednom primjeru kreiramo ofstream
objekat koji se naziva upis:
//kreiramo ofstream objekat koji se naziva upis
ofstream upis; // ofstream je tip podatka

Nakon kreiranja, objekat moramo asocirati sa odgovarajuim fajlom, te otvoriti taj fajl.
Kompletan proces asociranja i otvaranja fajla moemo obaviti koritenjem funkcije
open(). Prvi argument funkcije open() predstavlja naziv fajla sa kojim elimo
manipulisati:
upis.open("mojFajl.txt");

U prethodnom primjeru smo otvorili fajl pod nazivom mojFajl.txt, te samim tim izvrili
njegovo asocijaciranje sa objektom upis. Na jednostavniji i krai nain, prethodna dva
primjera (dvije linije koda) smo mogli napisati:
//kreiramo objekat upis, asociramo objekat sa fajlom, te automatski otvaramo fajl
ofstream upis("mojFajl.txt");

Bitno je napomenuti da, prilikom upisivanja sadraja, fajl ije smo ime kao argument
predali funkciji ne mora postojati. U sluaju da fajl ne postoji, on e biti automatski
kreiran. Nakon otvaranja, u fajl moemo upisati eljeni sadraj. Jedan od naina na koji
sadraj upisujemo u fajl je identian koritenju objekta cout<< tj. navedemo ime
objekta, znak redirekcije, te sadraj koji elimo upisati:
//imeObjekta<<"sadraj koji ce biti upisan u fajl";
upis<<"Ovo je tekst koji cemo upisati u fajl mojFajl.txt......\n";
upis<<"Fajl mojFajl.txt se nalazi u istom direktoriju kao i nas program.";

Asociranje fajla sa objektom se moe vriti navoenjem apsolutne ili relativne putanje do
fajla. Ukoliko se fajl nalazi u istom direktoriju kao i va program funkciji open() je
dovoljno predati samo ime fajla i njegovu ekstenziju. Narednim primjerom kreiramo fajl
mojFajl.txt i u njega upisujemo eljeni sadraj.
#include <iostream>
#include <fstream> //<-- nemojte zaboraviti ukljuciti fstream biblioteku
using namespace std;
void main() {
//kreiramo objekat tipa ofstrema koji se naziva upis
ofstream upis;
//pozivamo funkciju open() i predajemo joj relativnu putanju do fajla
upis.open("mojFajl.txt");
//navodimo tekst koji cemo upisati u fajl
upis<<"Ovo je tekst koji cemo upisati u fajl mojFajl.txt......\n";
upis<<"mojFajl.txt se nalazi u istom direktoriju kao i nas program";
//zatvaramo fajl
Programiranje I:: Vjebe
http://student.fit.ba/

ProgramiranjeI_sylabus.doc

Fakultet informacijskih tehnologija


denis@fit.ba

upis.close();
system("pause");
}

Na raunaru koritenom za pisanje ovog materijala, apsolutna putanja do direktorija


unutar kojeg se nalazi prikazani program je sljedea:
C:\Users\Denis\Documents\visual studio 2013\Projects\FileIO\FileIO

U direktoriju ija je putanja prikazana, prethodni program je kreirao novi fajl pod
nazivom mojFajl.txt i u njega upisao navedeni tekst. Velika je vjerovatnoa da
navedena putanja nee odgovarati onoj na vaem raunaru, zato odvojite malo vremena
da pronaete fajl koji je kreiran prethodnim programom i pogledajte njegov sadraj1.
U sluaju da se fajl nalazi na nekoj drugoj lokaciji, argument funkcije mora biti apsolutna
putanja do fajla. Kao ilustraciju:
1. na lokalnom disku (C:\) kreirajte direktorij koji se naziva Programiranje1
2. unutar prethodno kreiranog direktorija kreirajte jo jedan direktorij koji se naziva
FileIO.
Nakon to ste kreirali direktorije, napravite sljedee izmjene (umjesto relativne navedite
apsolutnu pitanju do fajla), te ponovo pokrenite program:
//pozivamo funkciju open() i predajemo joj apsolutnu putanju do fajla
upis.open("C:\\Programiranje1\\FileIO\\mojFajl.txt");

Nakon zavretka programa, ponovo otvorite prethodno kreirani direktorij C:\


Programiranje1 FileIO i vidjet ete da se u njemu nalazi fajl sa nazivom
mojFajl.txt. Ako ste sve dobro uradili, otvorite mojFajl.txt i u njemu bi se trebao
nalaziti sljedei sadraj:
Ovo je tekst koji cemo upisati u fajl mojFajl.txt......
mojFajl.txt se nalazi u istom direktoriju kao i nas program

Ukoliko ste pratili navedene korake vjerojatno ste primijetili da sadraj fajla nije ba
najtaniji pokazatelj trenutne lokacije naeg programa. Razlog tome je injenica da se
na
program
(.exe
fajl)
jo
uvijek
nalazi
na
lokaciji
C
C:\Users\Denis\Documents\visual studio 2013\Projects\FileIO\FileIO dok se
fajl u koji je upisan tekst nalazi u direktoriju C:\Programiranje1\FileIO.
Nakon zavretka rada, poeljno je da zatvorimo fajl. Ovaj postupak svakako treba
praktikovati kako bismo izbjegli nepotrebne komplikacije. Prije svega moe se desiti da,
nakon to smo zavrili rad s fajlom, neki drugi program ne bude u mogunosti pristupiti
fajlu. Zbog toga smo na kraju programa pozvali funkciju close(), te na taj nain
omoguili ponovno koritenje fajla. Nakon poziva funkcije close() kreirani objekat
(upis) moemo ponovo koristiti za rad sa nekim drugim fajlovima.
U prethodnom dijelu smo predstavili nain upisivanja sadraja u fajl. Meutim, kada
elimo itati sadraj fajla situacija je malo drugaija. Prije svega, za ispisivanje sadraja
fajla, potreban nam je objekat klase ifstream. Zatim, da bismo uitali odreeni sadraj,
fajl iz kojeg itamo mora postojati. Dakle, treba voditi rauna o sluajevima u kojima
1

Ukoliko koristite Visual Studio razvojno okruenje, najjednostavniji put da doete do fajla jeste da u okviru Solution Explorer-a napravite desni klik miem na
naziv projekta i odaberete opciju Open Folder in File Explorer

Programiranje I:: Vjebe


http://student.fit.ba/

ProgramiranjeI_sylabus.doc

Fakultet informacijskih tehnologija


denis@fit.ba

program nije u mogunosti otvoriti zahtijevani fajl (bilo da fajl ne postoji, da je oteen ili
da nemamo privilegije za pristup). Postoji jednostavan nain da provjerimo da li je na
fajl uspjeno otvoren, a to je koritenjem funkcije fail(). Pomenuta funkcija vraa
vrijednost true ukoliko postoji neki problem prilikom otvaranja fajla tj. vrijednost false
ukoliko je fajl uspjeno otvoren. Dakle, provjeru moemo vriti i na sljedei nain:
if(ispis.fail())//<--izmjene se odnose samo na provjeru uslova
cout<<"Greska: Nemoguce otvoriti zahtijevani fajl!\n";
else
cout<<"Otvaram sadrzaj fajla...\n";

Pojasnili smo nain na koji moemo upisivati neki sadraj u fajl, te provjeriti da li je fajl
uspjeno otvoren. U nastavku emo uraditi par primjera sa upisom i ispisom sadraja
fajla.
#include <iostream>
#include <fstream>
using namespace std;
void main(){
//naredne dvije linije daju isti rezultat
// char crt[] ="\n==============================================\n";
char * crt="\n==============================================\n";
//kreiramo objekat koji e omoguiti upis sadraja u fajl
//te ujedno otvaramo fajl mojFajl.txt
ofstream upis("mojFajl.txt");
//ako je dolo do greke pri otvaranju fajla, program ispisuje poruku
if(upis.fail())
cout<<"UPIS :: Greska: Nemoguce otvoriti fajl....\n";
else{
//naredni tekst upisujemo u fajl mojFajl.txt
upis<<crt<<"Univerzitet \"Dzemal Bijedic\""<<endl;
upis<<"Fakultet informacijskih tehnologija"<<endl;
upis<<"Sjeverni logor 12, Mostar"<<endl;
upis<<"Tel/Fax: +387 (0) 36 281 166"<<crt;
}
//upis je zavren, zatvaramo fajl
upis.close();
//**********************************************************
//kreiramo objekat za itanje - ispis sadraja fajla
ifstream ispis("mojFajl.txt");
if(ispis.fail())
cout<<"ISPIS :: Greska: Nemoguce otvoriti fajl....\n";
else{
//kreiramo varijablu koju emo koristiti u while petlji
char znak;
//sve dok u fajlu postoji sadraja,funkcija get() uzimaj znak po znak i
//smijesta ga u varijablu znak
while(ispis.get(znak))
cout<< znak;//ispisi trenutno ucitani znak
}
ispis.close();//kada je sadrzaj fajla ispisan, zatvaramo fajl
system("pause");
}

U prethodnom programu, vrili smo upis i ispis sadraja iz fajla koji se naziva
mojFajl.txt. Pomenuti fajl se nalazi u istom direktoriju kao i na program to moemo
zakljuiti na osnovu relativne putanje. Na poetku programa, koristei ofstream objekat
upis u fajl smo upisali osnovne informacije o naem Fakultetu, te odmah nakon toga
Programiranje I:: Vjebe
http://student.fit.ba/

ProgramiranjeI_sylabus.doc

Fakultet informacijskih tehnologija


denis@fit.ba

zatvorili fajl. Nakon upisa, kreirali smo novi objekt ispis koji nam je omoguio da
ispiemo sadraj fajla. Jedina novina u prethodnom programu jeste koritenje funkcije
get(). Naime, pri svakom izvrenju while petlje funkcija get() iz fajla uzima naredni
karakter i pohranjuje ga u varijablu znak koja je funkciji predata kao argument. Nakon
uitavanja, vrijednost varijable znak se ispisuje. Ukratko, petlja while e se ponavljati
sve dok funkcija get() iitava znakove, odnosno sve dok u fajlu postoji neki sadraj.
Zbog jednostavnije manipulacije, relativnu ili apsolutnu putanju do fajla je poeljno
pohraniti u jednu varijablu (niz karaktera) te koristiti kao argument prilikom asociranja
objekta sa fajlom.
void main(){
//.....
char * nazivFajla = "mojFajl.txt";
//.....
ofstream upis(nazivFajla);
//.....
ifstream ispis(nazivFajla);
//.....
}

Pored koritenja jednog karaktera, ispis sadraja nekog fajla moemo izvriti koristei
nizove karaktera to je predstavljeno u narednom primjeru:
#include <iostream>
#include <fstream>
using namespace std;
//u ovom primjeru crt smo deklarisali kao globalnu varijablu (pokazivac)
char * crt="==============================================\n";
void main(){
const int max=100;
//kreiramo niz od 100 karaktera u koji emo pohraniti
//jedan red sadraja fajla
char jedanRed[max];
char * nazivFajla = "mojFajl.txt";
ofstream upis(nazivFajla);
if(upis.fail())
cout<<"Greska: Nemoguce otvoriti fajl....\n";
else
//u fajl upisujemo dva reda teksta: crtice i FIT
upis<<crt<<"Fakultet informacijskih tehnologija";
upis.close();
ifstream ispis(nazivFajla);
//iz fajla iscitavamo prvi red teksta i upisujemo u niz jedanRed
ispis.getline(jedanRed,max);
//ispisujemo sadraj niza
cout<<jedanRed<<endl;
//iz fajla iscitavamo drugi red teksta i upisujemo u niz jedanRed
ispis.getline(jedanRed,max);
//ispisujemo sadraj niza
cout<<jedanRed<<endl;
ispis.close();
system("pause");
}

U prethodnom programu, za ispis sadraja fajla, koritena je funkcija getline().Funkcija


getline() iz fajla uzima prvi red teksta ili oznaeni broj karaktera (u naem sluaju

5
Programiranje I:: Vjebe
http://student.fit.ba/

ProgramiranjeI_sylabus.doc

Fakultet informacijskih tehnologija


denis@fit.ba

100) i upisuje ih u niz koji je naveden kao prvi argument (jedanRed). Nakon toga,
program ispisuje sadraj niza. Opisanu proceduru morali smo izvriti za svaki red teksta
koji se nalazi unutar fajla.
Koritenjem funkcije eof() end of file prethodni program moemo uiniti kraim i
itljivijim. Funkciju eof() najee koristimo u kombinaciji sa nekom od petlji (pri
provjeri uslova) koja treba da se izvrava sve dok unutar fajla postoji odreeni sadraj. U
prethodnom programu napravite sljedee izmjene.
ifstream ispis(nazivFajla);
while(!ispis.eof()){//sve do kraja fajla
//preuzimaj po jedan red teksta i pohrani ga u niz jedanRed
ispis.getline(jedanRed,max);
//ispii sadraj niza
cout<<jedanRed<<endl;
}
ispis.close();

Funkciju getline() jo jednostavnije moemo iskoristiti na sljedei nain:


ifstream ispis(nazivFajla);
while(ispis.getline(jedanRed,max))
cout<<jedanRed<<endl;
ispis.close();

U narednom programu korisniku smo omoguili da definie naziv fajla kao i sadraj koji u
njega eli pohraniti. Nakon unosa, program treba da ispie sadraj fajla. Ako ste paljivo
itali prethodni dio materijala trebalo biste biti u stanju samostalno napraviti ovaj
program.
#include <iostream>
#include <fstream>
using namespace std;
char * crt ="\n===============================================\n";
void main(){
const int maxTekst=200;
const int maxFajl=30;
char tekst[maxTekst];
char nazivFajla[maxFajl];
cout<<crt<<"\t\tFile I/O"<<crt;
cout<<"Unesite naziv fajla i njegovu ekstenziju: ";
cin.getline(nazivFajla,maxFajl);
ofstream upis(nazivFajla);
if(upis.fail())
cout<<crt<<"Greska prilikom otvaranja fajla!"<<crt;
else{
cout<<crt<<"Unesite sadrzaj fajla: ";
cin.getline(tekst,maxTekst);
upis<<crt<<tekst<<crt;
}
upis.close();
system("cls");
ifstream ispis(nazivFajla);
if(ispis.fail())
cout<<crt<<"Greska prilikom otvaranja fajla!"<<crt;
else{
char znak;
cout<<crt<<"FAJL:\t"<<nazivFajla<<crt;
Programiranje I:: Vjebe
http://student.fit.ba/

ProgramiranjeI_sylabus.doc

Fakultet informacijskih tehnologija


denis@fit.ba

cout<<"SADRZAJ: ";
while(ispis.get(znak))
cout<<znak;
}
ispis.close();
system("pause");
}

Ono to ste vjerovatno primjetili u prethodnim primjerima jeste injenica da ukoliko dva
puta pokrenete program i unesete isto ime fajla, a razliit tekst, u fajlu e ostati zapisan
(sauvan) samo posljednje uneseni tekst. Razlog tome je injenica da se svakim novim
pokretanjem programa stari sadraj fajla prepisuje. Upravo u ovakvim sluajevima je
potrebno koristiti odgovarajue modove koji omoguavaju definisanje dodatnih postavki
prilikom rada sa fajlovima. U okviru ovog materijala opisati emo neke od najee
koritenih modova, a to su:
MOD
ios::in
ios::out
ios::app
ios::ate
ios::trunc
ios::_Nocreate
ios::binary

OPIS
Otvara fajl za itanje
Otvara fajl za pisanje i brie zateeni sadraj
Novi sadraj dodaje na kraj fajla
Otvara fajl i pomjera pokaziva na kraj fajla
Ako fajl postoji, njegov sadraj se odbacuje brie
Zahtijevani fajl mora postojati (nee biti automatski kreiran)
Otvara fajl u binarnom modu (podaci se ne prevode)

Prikazane modove navodimo unutar funkcije open(), odmah nakon naziva fajla. U
prethodnom primjeru izmijenite sljedeu liniju koda i ponovo pokrenite program.
//ostatak programa ostaje isti
ofstream upis(nazivFajla, ios::app); //<--dodajte mod
if(upis.fail())
cout<<crt<<"Greska prilikom otvaranja fajla!"<<crt;

Program pokrenite dva puta i svaki puta navedite isti naziv fajla, ali unesite razliit tekst.
Primjeujete da se napravljenim izmjenama (koritenjem moda ios::app) novi sadraj
dodaje na kraj fajla, pri emu prethodni sadraj fajla ostaje nepromijenjen.
Bitno je znati da su neki od pomenutih modova podrazumijevani tj. defaultni. Za
ofstream objekte defaultni mod je ios::out, dok je za ifstream objekte defaultni mod
ios::in.
ofstream upis;
//zato to ofstream objekti imaju defaultni mod ios::out naredne dvije linije imaju
//isto znaenje
upis.open(nazivFajla);
upis.open(nazivFajla, ios::out);

Prilikom otvaranja fajla moemo koristiti vie modova koje moramo razdvojiti koristei
znak pipe (|). Pogledajte sljedei primjer:
//izmedju modova koristimo znak pipe (|)
upis.open(nazivFajla, ios::out | ios::app);

Pored navedenih, postoji i fstream klasa iji objekti imaju dva defaultna moda: ios::in i
ios::out. Na osnovu toga moemo zakljuiti da se objekti tipa fstream mogu koristiti za

7
Programiranje I:: Vjebe
http://student.fit.ba/

ProgramiranjeI_sylabus.doc

Fakultet informacijskih tehnologija


denis@fit.ba

upisivanje i za itanje sadraja fajla. Pokuajte jedan od prethodnih primjera napraviti


koristei objekat tipa fstream.
Kretanje kroz sadraj fajla nam omoguava ulazni (pri upisu sadraja) i izlazni (pri ispisu
sadraja) pokaziva. Kada otvorimo fajl, pokaziva se nalazi na samom poetku fajla
na prvom karakteru (ukoliko drugaije ne zahtijevamo). Upravo zbog toga mi smo u
mogunosti da itamo sadraj fajla od poetka do kraja. U tabeli modova smo naveli da
mod ios::ate omoguava pomijeranje pokazivaa na kraj fajla. Upravo to predstavlja
glavni razlog zato naredni primjer nee prikazati sadraj fajla.
#include <iostream>
#include <fstream>
using namespace std;
void main(){
char * nazivFajla = "mojFajl.txt";
ofstream upis(nazivFajla);
if(upis.fail())
cout<<"Greska prilikom otvaranja fajla"<<endl;
else
upis<<"Fakultet informacijskih tehnologija::www.fit.ba";
upis.close();
//prilikom otvaranja fajla,koristeci mod ios::ate pokaziva se pomijera
na
//kraj, tako da funkcija get() nee pronai niti jedan karakter koji
//bi mogla ispisati
ifstream ispis(nazivFajla,ios::ate); //ios::ate
if(ispis.fail())
cout<<"Greska prilikom otvaranja fajla"<<endl;
else{
char znak;
while(ispis.get(znak))
cout<<znak;
}
ispis.close();
system("pause");
}

Takoer, postoje funkcije koje nam omoguavaju pomijeranje pokazivaa na odreenu


lokaciju unutar fajla kao i oitavanje njegove trenutne lokacije:
Funkcija

OPIS

seekg()

Na zadatu lokaciju pomjera pokaziva za itanje sadraja fajla, a koristi se sa


ifstream objektom

tellg()

Vraa (oitava) poziciju pokazivaa za itanje

seekp()

Na zadatu lokaciju pomjera pokaziva za upisivanje sadraja fajla, a koristi se sa


ofstream objektom

tellp()

Vraa (oitava) poziciju pokazivaa za upisivanje

Naredni primjer ilustruje nain koritenja funkcija za pomijeranje pokazivaa unutar fajla.
Poto smo u prethodnom primjeru kreirali fajl mojFajl.txt i u njega upisali:Fakultet
informacijskih tehnologija::www.fit.ba, sada emo korisniku dati mogunost da
odredi lokaciju od koje e se ispisati sadraj fajla. Pogledajte sljedei primjer:
#include <iostream>
#include <fstream>
using namespace std;
void main(){

8
Programiranje I:: Vjebe
http://student.fit.ba/

ProgramiranjeI_sylabus.doc

Fakultet informacijskih tehnologija


denis@fit.ba

int brojMjesta=0;
char znak;
char * nazivFajla = "mojFajl.txt";
ifstream ispis(nazivFajla);
if(ispis.fail())
cout<<"Greka prilikom otvaranja fajla."<<endl;
else{
cout<<"Za koliko mjesta zelite pomjeriti pokazivac: ";
cin>>brojMjesta;
// pomijeramo pokaziva za eljeni broj mjesta
ispis.seekg(brojMjesta);
while(ispis.get(znak)){
//oitavamo trenutnu lokaciju pokazivaa koristei
//funkciju tellg()
cout<<"\nPokazivaca je na lokaciji: "<<ispis.tellg();
cout<<" a tu se nalazi znak :"<<znak;
}
}
ispis.close();
cout<<endl;
system("pause");
}

Ukoliko prethodni program elite uiniti modularnijim, aktivnosti ispisa moete prepustiti
nekoj od funkcija npr. funkciji Prikazi:
#include <iostream>
#include <fstream>
using namespace std;
//funkcija prikazi kao argument prima referencu na objekat tipa ifstream
void Prikazi (ifstream & ispis){
int brojMjesta=0;
char znak;
cout<<"Za koliko mjesta zelite pomjeriti pokazivac: ";
cin>>brojMjesta;
ispis.seekg(brojMjesta);
while(ispis.get(znak)){
cout<<"\nPokazivaca je na lokaciji: "<<ispis.tellg();
cout<<" a tu je znak :"<<znak;
}
}
void main(){
char * nazivFajla = "mojFajl.txt";
ifstream ispis(nazivFajla);
if(ispis.fail())
cout<<"Greka prilikom otvaranja fajla."<<endl;
else
Prikazi(ispis);
ispis.close();
system("pause");
}

U nekim sluajevima e nam biti potrebna informacija o tome je li neki fajl otvoren ili
zatvoren. Pomenutu dilemu rjeavamo koritenjem funkcije is_open(). Ukoliko je fajl
otvoren funkcija vraa vrijednost true, a u suprotnom funkcija vraa false
#include <iostream>
#include <fstream>
using namespace std;

9
Programiranje I:: Vjebe
http://student.fit.ba/

ProgramiranjeI_sylabus.doc

Fakultet informacijskih tehnologija


denis@fit.ba

char * crt="\n============================\n";
void main(){
ofstream upis("mojFajl.txt");
cout<<crt<<"Otvaram fajl....."<<crt;
if(upis.is_open())
cout<<"Fajl je otvoren"<<crt;
else
cout<<"Fajl je zatvoren";
cout<<"Zatvaram fajl....."<<crt;
upis.close();
if(upis.is_open())
cout<<"Fajl je otvoren"<<crt;
else
cout<<"Fajl je zatvoren"<<crt;
system("pause");
}

Za kraj prie o tekstualnim fajlovima pomenut emo i sluajeve kada numerike


vrijednosti koje smo pohranili u odreeni fajl elimo ponovo koristiti kao numerike
(prilikom kalkulacija, provjere i sl.). Ukoliko to elimo postii, numerike vrijednosti koje
su pohranjene u fajlu (u tekstualnom formatu) moramo na odgovarajui nain
konvertovati. U narednom primjeru, korisniku smo omoguili da unese pinove korisnika
te ih pohranili u tekstualni fajl. Nakon toga, sauvane pinove uitavamo u na program,
te ih konvertujemo koristei atoi funkciju (koju smo predstavili u prethodnom
materijalu).
#include <iostream>
#include <fstream>
using namespace std;
void main(){
char * nazivFajla = "pinovi.txt";
const int max = 5;
int pinovi1[max];//korisnik unosi pinove u niz pinovi1
int pinovi2[max];//pinove iz fajla ucitavamo u niz pinovi2
ofstream upis(nazivFajla);
for(int i=0;i<max;i++){
cout<<"Unesite "<<i+1<<" pin: ";
cin>>pinovi1[i];
//odmah nakon unosa PIN upisujemo u fajl
//takodjer nismo vrsili provjeru da li je fajl otvoren
upis<<pinovi1[i]<<endl;
}
upis.close();
ifstream ispis(nazivFajla);
if(!ispis.fail()){
//pod pretpostavkom da pin nece biti duzi od 4 znamenke
char charPin[max];
cout<<"\n::UCITANI PINOVI::\n";
for(int i=0;i<max;i++){
//iscitavamo pinove iz fajla i upisujemo ih u niz charPin
ispis.getline(charPin,max);
//konvertujemo ucitani pin
pinovi2[i] = atoi(charPin);
cout<<"Pin["<<i+1<<"]: "<<pinovi2[i]<<endl;
}
}else
cout<<"Greska prilikom otvaranja fajla!"<<endl;
ispis.close();
system("pause");

10
Programiranje I:: Vjebe
http://student.fit.ba/

ProgramiranjeI_sylabus.doc

Fakultet informacijskih tehnologija


denis@fit.ba

Manipulisanje binarnim fajlovima


Na poetku ovog materijala iznijeli smo konstataciju da koritenje binarnih fajlova
omoguava bru manipulaciju podacima. Rad sa binarnim fajlovima je dosta slian radu
sa tekstualnim fajlovima, ali ipak postoje odreene razlike. Prije svega, prilikom
otvaranja fajla moramo naglasiti da radimo u binarnom (ios::binary) modu. Kada
odreeni sadraj elimo pohraniti u binarnom formatu onda koristimo write() funkciju.
Funkcijom write() kopiramo odreeni broj bajta iz memorije u asocirani fajl. Analogno
tome, za ispis sadraja koji je pohranjen u binarnom formatu koristimo read() funkciju.
Da bismo ilustrovali rad sa binarnim fajlovima u narednom primjeru korisniku emo
omoguiti da inicijalizuje atribute objekta student1 (objekat je tipa Student) koje emo
pohraniti u binarnom formatu. Nakon toga, koristei sadraj binarnog fajla inicijalizujemo
atribute objekta student2. Pogledajte sljedei primjer:
#include <iostream>
#include <fstream>
using namespace std;
char * crt="\n==================================================\n";
struct Student{
int brojIndexa;
char imePrezime[30];
};
//funkcije za unos i ispis vrijednosti atributa objekata tipa Student
void Unos(Student & student){
cout<<crt<<"Uneiste ime i prezime studenta: ";
cin.getline(student.imePrezime,30);
cout<<"Uneiste broj indexa: ";
cin>>student.brojIndexa;
cin.ignore();
}
void Ispis(const Student & student){
cout<<crt<<"Ime i prezime: "<<student.imePrezime<<endl;
cout<<"Broj indexa: "<<student.brojIndexa<<crt;
}
void main(){
const int max = 20;
char nazivFajla[max];
//objekat ije vrijednosti atributa upisujemo u fajl
Student student1;
//objekat ije vrijednosti atributa inicijalizujemo na osnovu sadraja
fajla
Student student2;
cout<<crt<<"\t\t::STUDENT 1::";
//inicijalizujemo vrijednosti atributa prvog studenta
Unos(student1);
cout<<crt<<"Unesite ime fajla: ";
cin.getline(nazivFajla,max);
//otvaramo fajl za upis u binarnom formatu - ios::binary mod
ofstream objekatUnos(nazivFajla,ios::out | ios::binary);
cout<<crt<<"Objekat STUDENT1 upisujem u fajl: "<<nazivFajla<<crt;
//koristeci funkciju write() objekat student1 upisujemo u fajl
objekatUnos.write((char*)(&student1),sizeof(student1));
objekatUnos.close();

11
Programiranje I:: Vjebe
http://student.fit.ba/

ProgramiranjeI_sylabus.doc

Fakultet informacijskih tehnologija


denis@fit.ba

cout<<crt<<"Sadrzajem fajla "<<nazivFajla<<" inicijalizujem objekat


STUDENT2"<<crt;
//otvaramo fajl za ispis binarnog sadraja
ifstream objekatIspis(nazivFajla,ios::in | ios::binary);
//sadrajem fajla, koristei funkciju read(), inicijalizujemo atribute
//objekta student2
objekatIspis.read((char*)(&student2),sizeof(student2));
cout<<crt<<"\t\t::STUDENT 2::";
//kao dokaz, koristeci funkciju Ispis ispisujemo vrijednosti obiljeja
studenta 2
Ispis(student2);
objekatIspis.close();
system("pause");
}

Pokrenite prethodni program, unesite vae podatke i naziv fajla (npr. mojiPodaci.bin).
Nakon toga pronaite fajl koji ste kreirali i vidjeti ete da njegov sadraj nije u potpunosti
razumljiv (fajl pokuajte otvoriti unutar Visual Studio-a).
Poto do sada nismo govorili o koritenju read() i write() funkcija u nastavku emo ih
ukratko predstaviti. Vidjeli smo da obje funkcije primaju dva argumenta. Prvi argument
je pokaziva (tipa char) na lokaciju iz koje itamo ili u koju upisujemo odreeni sadraj.
U prethodnom programu kod funkcije write() kao prvi argument smo naveli pokaziva
(char *) na objekat student1. Jednostavno moemo rei da prvi argument funkcije
write() oznaava lokaciju od koje funkcija treba da zapone upisivanje podataka u fajl.
Broj bajta koje planiramo upisati je definisan drugim argumentom funkcije (za
odreivanje broja bajta koristili smo sizeof() funkciju). Dakle, funkciji write() moramo
naznaiti odakle i koliko podataka treba upisati u fajl. Na identian nain se koristi i
funkcija read().

upis.write((char*)(&student1),sizeof(student1));

char pokaziva na objekt iji


sadraj upisujemo u fajl

Broj bajta koji e se upisati u


fajl

Prethodni program pokuajte nadograditi na nain da korisniku omoguite inicijalizaciju


podataka za vei broj studenata (niz studenata) koji e biti sauvani u binarnom formatu.
Nakon toga, sauvane podatke uitajte u drugi niz (studenata) i ispiite njihove
vrijednosti.
Nadam se da ste razumjeli osnovne pojmove i funkcije koje koristimo prilikom
manipulacije fajlovima. Treba naglasiti da ovaj materijal predstavlja samo mali uvod u
jako veliko podruje koje opisuje rad sa fajlovima, a naredni primjer ima zadatak da
demonstrira koritenje savladanog gradiva.
#include <iostream>
#include <fstream>
using namespace std;
char * crt="\n==========================================================\n";
char * poruka_o_gresci = "Greska prilikom otvaranja fajla!";
void UnosSadrzaja(const char * nazivFajla){
cout<<crt<<"\t\t::UNOS SADRZAJA::"<<crt;
const int max = 200;
Programiranje I:: Vjebe
http://student.fit.ba/

12

ProgramiranjeI_sylabus.doc

Fakultet informacijskih tehnologija


denis@fit.ba

char tekst[max];
ofstream upis(nazivFajla);
if(upis.fail())
cout<<crt<<poruka_o_gresci<<crt;
else{
cout<<"Unesite tekst: ";
cin.getline(tekst,max);
upis<<tekst;
cout<<crt<<"Sadrzaj upisan u fajl!"<<crt;
}
upis.close();
}
void PrikazSadrzaja(const char * nazivFajla){
cout<<crt<<"\t\t::PRIKAZ SADRZAJA::"<<crt;
char znak;
//zahtjevani fajl mora postojati jer koristimo ios::_Nocreate mod
ifstream ispis(nazivFajla, ios::in | ios::_Nocreate);
if(ispis.fail())
cout<<crt<<poruka_o_gresci<<crt;
else{
cout<<crt<<"FAJL: "<<nazivFajla<<crt<<"SADRZAJ:"<<crt;
while(ispis.get(znak))
cout<<znak;
cout<<crt<<"Sadrzaj fajla prikazan!"<<crt;
}
ispis.close();
}
void DodavanjeSadrzaja(const char * nazivFajla){
cout<<crt<<"\t\t::DODAVANJE SADRZAJA::"<<crt;
const int max = 200;
char noviTekst[max];
//fajl mora postojati - ios::_Nocreate
//novi sadrzaj ce biti dodat na kraj fajla - ios::app
ofstream upis(nazivFajla, ios::app | ios::_Nocreate);
if(upis.fail())
cout<<crt<<poruka_o_gresci<<crt;
else{
cout<<"Unesite tekst koji zelite dodati: ";
cin.getline(noviTekst,max);
upis<<endl<<noviTekst<<endl;
cout<<crt<<"Novi sadrzaj uspjesno dodat."<<endl;
}
upis.close();
}
void KopiranjeSadrzaja(const char * nazivFajla){
cout<<crt<<"\t\t::KOPIRANJE SADRZAJA::"<<crt;
const int max = 30;
char nazivNovogFajla[max];
char znak;
cout<<"Unesite ime fajla u koji zelite kopirati sadrzaj: ";
cin.getline(nazivNovogFajla,max);
//otvaramo fajl odakle kopiramo
ifstream ispis(nazivFajla, ios::in | ios::_Nocreate);
//otvaramo fajl gdje kopiramo
ofstream upis(nazivNovogFajla,ios::app);
if(!ispis.fail()){//provjeravmo validnost izvornog fajla
if(!upis.fail()){//provjeravmo validnost destinacijskog fajla
while(ispis.get(znak))//uzimamo naredni karakter
upis<<znak;//i upisujemo ga u destinacijski fajl
cout<<crt<<"Sadrzaj fajla: "<<nazivFajla;
cout<<" uspjesno dodat fajlu: "<<nazivNovogFajla<<crt;
Programiranje I:: Vjebe
http://student.fit.ba/

13

ProgramiranjeI_sylabus.doc

Fakultet informacijskih tehnologija


denis@fit.ba

}
else
cout<<crt<<"Destinacijski::"<<poruka_o_gresci<<crt;
}
else
cout<<crt<<"Izborni::"<<poruka_o_gresci<<crt;
ispis.close();
upis.close();
}
int VelicinaFajla(const char * nazivFajla){
cout<<crt<<"\t\t::VELICINA FAJLA::"<<crt;
ifstream ispis(nazivFajla);
if(!ispis.fail()){
//pomijeramo pokaziva na kraj fajla
ispis.seekg(0,ios::end);
//oitavamo poziciju pokazivaa, sto predstavlja broj bajta
int velicina = ispis.tellg();
cout<<"Velicina fajla je: "<<velicina<<" bajta."<<crt;
ispis.close();
return velicina;
}else
cout<<crt<<poruka_o_gresci<<crt;
return -1;
}
void PretragaSadrzajaKarakter(const char * nazivFajla){
cout<<crt<<"\t\t::PRETRAGA::"<<crt;
char znak, trazeni;
int ukupno=0, pronadjeno=0;
ifstream ispis(nazivFajla);
cout<<"Unesite znak koji trazite: ";
cin>>trazeni;
cin.ignore(100,'\n');
if(!ispis.fail()){
while(ispis.get(znak)){
if(znak==trazeni)
pronadjeno++;
ukupno++;
}
cout<<crt<<"Fajl "<<nazivFajla<<" ima ukupno ";
cout<<ukupno<<" znakova.";
cout<<crt<<"Znak '"<<trazeni<<"' se nalazi na ";
cout<<pronadjeno<<" mjesta.";
}
else
cout<<crt<<poruka_o_gresci<<crt;
ispis.close();
}
void PretragaSadrzajaRijec(const char * nazivFajla){
//ZA
//1.
//2.
//3.
//

VJEZBU
sadrzaj fajla ucitati u niz alociran u dinamickoj memoriji
korisniku omoguciti da unese rijec koju trazi
izvrsiti pretragu ucitanog sadrzaja fajla (niza),
te o rezulatima pretrage obavijestiti korisnika

}
void BrisanjeSadrzaja(const char * nazivFajla){
cout<<crt<<"\t\t::BRISANJE SADRZAJA::"<<crt;
ofstream ispis(nazivFajla, ios::trunc);
//isto bismo postigli da smo umjesto ios::trunc napisali ios::out
if(!ispis.fail())
cout<<crt<<"Sadrzaj fajla "<<nazivFajla<<" obrisan!"<<crt;
else
Programiranje I:: Vjebe
http://student.fit.ba/

14

ProgramiranjeI_sylabus.doc

Fakultet informacijskih tehnologija


denis@fit.ba

cout<<crt<<poruka_o_gresci<<crt;
}
//da li je izbor trebao biti povratna vrijednost?
void prikaziMeni(int & izbor){
do{
cout<<crt<<"\t\t::MANIPULISANJE FAJLOVIMA::"<<crt;
cout<<"1. Upisi sadrzaj u fajl. "<<endl;
cout<<"2. Prikazi sadrzaj fajla. "<<endl;
cout<<"3. Dodaj novi sadrzaj fajlu. "<<endl;
cout<<"4. Kopiraj sadrzaj fajla u drugi fajl. "<<endl;
cout<<"5. Pretrazuj sadrzaj fajla (karakter). "<<endl;
cout<<"6. Pretrazuj sadrzaj fajla (rijec). "<<endl;
cout<<"7. Prikazi velicinu fajla. "<<endl;
cout<<"8. Brisi sadrzaj fajla. "<<endl;
cout<<"9. Rad sa novim fajlom. "<<endl;
cout<<"10. Izadji iz programa. "<<crt;
cout<<"Unesite vas izbor: ";
cin>>izbor;
cin.ignore();
system("cls");
}while(izbor<1 || izbor>10);
}
void main(){
int izbor = 1;
const int max = 30;
char nazivFajla[max];
do{
cout<<crt<<"\t\t::MANIPULISANJE FAJLOVIMA::"<<crt;
cout<<"Unesite ime fajla i ekstenziju: ";
cin.getline(nazivFajla,max);
do{
prikaziMeni(izbor);
switch(izbor){
case 1:
UnosSadrzaja(nazivFajla);break;
case 2:
PrikazSadrzaja(nazivFajla);
break;
case 3:
DodavanjeSadrzaja(nazivFajla);break;
case 4:
KopiranjeSadrzaja(nazivFajla);break;
case 5:
PretragaSadrzajaKarakter(nazivFajla);break;
case 6:
PretragaSadrzajaRijec(nazivFajla); break;
case 7:
VelicinaFajla(nazivFajla); break;
case 8:
BrisanjeSadrzaja(nazivFajla); break;
}
}while(izbor!=9 && izbor!=10);
}while(izbor!=10);
system("pause");
}

Da biste potvrdili svoje znanje o rada sa fajlovima, prethodnom programu pokuajte


dodati opcije za manipulaciju binarnim fajlovima.

15
Programiranje I:: Vjebe
http://student.fit.ba/

You might also like