---
# System prepended metadata

title: Datotekte
tags: [Programiranje koristeći Python]

---

Datoteke
========

Čuvanje rezultata izvršavanja programa ili važnih podataka predstavlja temeljnu funkcionalnost u većini modernih aplikacija. Bez mogućnosti trajnog skladištenja, svi podaci proizvedeni tokom izvršavanja programa postaju privremeni i nepovratno se gube nakon završetka procesa. Ova ograničenja posebno su problematična u aplikacijama koje zahtijevaju kontinuirano praćenje ili upotrebu podataka kroz duži vremenski period. Na primjer, u video igrama, rezultati poput najboljih ostvarenja bi nestali po zatvaranju igre, čime bi se gubila motivacija korisnika za takmičenje. Slično tome, aplikacije koje upravljaju korisničkim postavkama ili personalizovanim unosima bile bi neupotrebljive bez mogućnosti čuvanja ovih podataka između sesija.

Omogućavanjem trajnog skladištenja podataka putem rada sa datotekama, programi postaju fleksibilniji, funkcionalniji i bolje prilagođeni stvarnim potrebama korisnika. Rad sa datotekama omogućava zapisivanje, čuvanje i kasnije čitanje podataka, kako u formatima koji su razumljivi ljudima (tekstualne datoteke), tako i u binarnim formatima koji su prilagođeni računarima.

Primjene ove funkcionalnosti su izuzetno široke i uključuju:
- **Čuvanje rezultata korisničkih aktivnosti**, poput igara, aplikacija za učenje ili sportskih praćenja.
- **Logiranje grešaka i aktivnosti**, što je ključno za razvoj i održavanje softvera.
- **Analizu podataka**, gdje se podaci sakupljeni iz različitih izvora trajno skladište radi statističke obrade ili izvještavanja.
- **Skladištenje velikih skupova podataka**, kao što su baze podataka, korisnički profili ili arhivske informacije.

Rad sa datotekama predstavlja neizostavan dio razvoja softverskih rješenja, jer omogućava programima da pređu granicu privremenih, jednokratnih procesa i postanu alati za dugotrajnu upotrebu.

## Radna memorija i čvrsti disk

U uvodnom dijelu naglašena je važnost trajnog skladištenja podataka kako bi se programi mogli koristiti u stvarnim situacijama, gdje je očuvanje podataka ključno za njihovu funkcionalnost. Ova potreba proizlazi iz osnovne razlike između **radne memorije (RAM)** i **čvrstog diska** (ili drugog trajnog skladišta podataka).

**Radna memorija (RAM)** koristi se za privremeno čuvanje podataka tokom izvršavanja programa. Svi podaci pohranjeni u RAM-u gube se nakon završetka programa ili gašenja računara. Zbog toga programi koji se oslanjaju samo na RAM ne mogu sačuvati rezultate ili podatke za buduću upotrebu. Učitavanje podataka u varijable je u suštini čuvanje podataka u radnoj memoriji, te ove vrijednosti nestaju gašenjem programa, jer se radna memorija briše.

S druge strane, **čvrsti disk** omogućava trajno skladištenje podataka. Kada se sadržaj datoteka čuva na čvrstom disku, podaci ostaju dostupni i nakon završetka rada programa, gašenja računara ili čak prenosa na drugi uređaj.


### Proces interakcije s datotekama

Tokom rada s datotekama, podaci obično prelaze iz jednog skladišnog prostora u drugi:
1. **Čitanje podataka** – Sadržaj datoteke smješten na čvrstom disku učitava se u radnu memoriju, gdje ga program može obrađivati. Ovo omogućava analizu, modifikaciju i prikaz podataka korisnicima.
2. **Pisanje podataka** – Nakon obrade, podaci iz radne memorije zapisuju se na čvrsti disk kako bi se osigurala njihova trajnost. Ovo se koristi za kreiranje novih datoteka ili ažuriranje postojećih.

Radna memorija osigurava brz pristup podacima tokom rada programa, dok čvrsti disk osigurava trajnost. Kombinovanjem ove dvije komponente postiže se optimalan balans između performansi i dugotrajnosti, što je ključna karakteristika efikasnih softverskih rješenja.

## Vrste datoteka

Prije rada sa datotekama, neophodno je razumjeti osnovne vrste datoteka:

1. **Tekstualne datoteke**  
   Tekstualne datoteke sadrže podatke u formatu čitljivom za ljude, kao što su `.txt`, `.csv` ili `.json`. Ove datoteke koriste standardne karaktere i pogodne su za zapisivanje i čitanje informacija koje korisnici jednostavno razumiju.

2. **Binarne datoteke**  
   Binarne datoteke sadrže podatke u formatu čitljivom za računare i često se koriste za skladištenje sadržaja poput slika, videozapisa ili programa. Primjeri ovakvih datoteka uključuju formate poput `.jpg`, `.png`, `.mp4` i `.exe`. Ove datoteke ne sadrže tekstualni sadržaj, već binarne podatke koji zahtijevaju specijalizovane alate za njihovu interpretaciju.
   
   Sadržaj binarnih datoteka može se korisnicima predstaviti na razumljiv način kroz različite programe ili uređaje. Na primjer, slike u formatima poput `.jpg` i `.png` prikazuju se korištenjem preglednika slika, grafičkih alata ili ugrađenih aplikacija operativnog sistema. Videozapisi u formatu `.mp4` reprodukuju se pomoću multimedijalnih plejera koji dekodiraju binarni sadržaj i prikazuju ga u obliku vizualnog i audio izlaza. S druge strane, programi u formatu `.exe` predstavljaju izvršne datoteke koje se direktno pokreću na računarima, omogućavajući realizaciju specifičnih funkcionalnosti koje su implementirane u njihovom kodu.


U daljem tekstu, fokus će biti na radu s tekstualnim datotekama u formatu `.txt`, jer one predstavljaju najjednostavniji i najpristupačniji način za demonstraciju osnovnih operacija s datotekama. Iako će primjeri koristiti tekstualne datoteke, principi rada s datotekama su univerzalni, pa se tehnike mogu primijeniti i na druge formate, uključujući binarne datoteke.


## Osnovne operacije sa datotekama

Za razumijevanje ključnih funkcionalnosti rada sa datotekamam, u nastavku će biti predstavljene osnovne operacije nad datotekama. Ove operacije obuhvataju:
1. Otvaranje datoteka;
2. Čitanje sadržaja;
3. Upisivanje sadržaja;
4. Zatvaranje datoteka.

Svaka od navedenih operacija igra važnu ulogu u pravilnom upravljanju datotekama i omogućava efikasan rad s podacima. Kombinovanjem ovih operacija, moguće je ostvariti ispravan i kompletan tok rada. Na primjer, otvaranjem datoteke priprema se pristup podacima, dok čitanje ili upisivanje omogućava manipulaciju sadržajem. Konačno, zatvaranjem datoteke osigurava se da su svi resursi oslobođeni i da su podaci ispravno sačuvani. Ovaj tok rada čini osnovu svakog programa koji koristi datoteke, bez obzira na njihovu vrstu ili primjenu.


### Otvaranje datoteka

Pristup datotekama ostvaruje se pomoću funkcije `open()`. Datoteka se otvara u specifičnom režimu rada (`mode`), koji određuje da li će se datoteka čitati, pisati ili obrađivati na drugi način. Režim se navodi kao drugi parametar funkcije, odmah iza naziva datoteke koja se obrađuje.

```python=
# Otvaranje datoteke u režimu za čitanje (read mode)
datoteka = open("primjer.txt", "r")
```

Najčešće korišteni režimi su:
- **`r`**: Čitanje datoteke. Datoteka mora postojati da bi se koristila.
- **`w`**: Pisanje u datoteku. Ako datoteka već postoji, njen sadržaj će biti obrisan.
- **`a`**: Dodavanje u datoteku (engl. *append*). Novi sadržaj dodaje se na kraj datoteke bez brisanja postojećeg sadržaja.
- **`b`**: Rad sa binarnim datotekama (koristi se u kombinaciji sa drugim režimima, npr. `rb` za čitanje binarnih datoteka).

:::info
#### Podrazumijevani režim
Ako režim nije eksplicitno naveden prilikom korištenja funkcije `open()`, koristi se podrazumijevani režim `r` (čitanje). U tom slučaju, datoteka mora postojati; u suprotnom, Python će prijaviti grešku `FileNotFoundError`.
:::

:::warning
Kako je ranije navedeno, ali je izuzetno važno za naglasiti, za režim čitanja `w`, datoteka može ranije postojati, ali se u tom slučaju njen raniji sadržaj u potpunosti briše, što može dovesti do neželjenog gubljenja podataka!
:::

### Zatvaranje datoteka

Kada se završi rad sa datotekom, potrebno je istu zatvoriti pomoću metode `close()`. Zatvaranje datoteke je ključno iz dva razloga:
* Prvo, oslobađaju se svi resursi koje je sistem koristio za održavanje otvorene datoteke. 
* Drugo, osigurava se da su svi podaci koji su zapisani u datoteku pravilno pohranjeni na disk, čime se izbjegava mogućnost gubitka ili oštećenja podataka. 

Bez zatvaranja datoteke, sistem može zadržati nepohranjene podatke u privremenoj memoriji (engl. *buffer*), što može rezultirati nepotpunim ili neispravnim zapisom.

Primjer zatvaranja datoteke prikazan je ispod:

```python=
datoteka.close()
```

Kao dobra praksa, zatvaranje datoteka se preporučuje u svim programima kako bi se osigurala ispravnost podataka i optimalno korištenje resursa sistema.

### Rad sa kontekstnim menadžerom

Korištenje kontekstnog menadžera `with` predstavlja pouzdan i efikasan način rada s datotekama u Pythonu. Ovaj pristup automatizuje proces zatvaranja datoteke, čime se smanjuje rizik od grešaka koje nastaju zaboravljanjem poziva metode `close()`. Kada se koristi kontekstni menadžer, datoteka se automatski zatvara čim se izađe iz bloka koda unutar `with` konstrukcije, čak i ako dođe do greške tokom izvršavanja koda.

Ovaj način rada omogućava čitljiviji i organizovaniji kod, što je naročito korisno u složenijim aplikacijama. Primjer čitanja datoteke pomoću kontekstnog menadžera prikazan je ispod.

```python=
with open("primjer.txt", "r") as datoteka:
    sadrzaj = datoteka.read()
    print(sadrzaj)
```

U ovom primjeru, datoteka se otvara u režimu za čitanje (`r`), njen sadržaj se čita metodom `read()` i ispisuje na ekran pomoću funkcije `print()`. Po završetku bloka `with`, Python automatski zatvara datoteku, oslobađajući resurse i osiguravajući pravilno skladištenje podataka.

Korištenje kontekstnog menadžera nije ograničeno samo na čitanje datoteka. Ovaj pristup se podjednako koristi za zapisivanje, dodavanje i rad sa binarnim datotekama.

Ovaj pristup se preporučuje kao standardna praksa u svim programima koji rade s datotekama.


### Čitanje sadržaja datoteka

Nakon otvaranja datoteke u režimu za čitanje (`r`), moguće je pristupiti njenom sadržaju korištenjem različitih metoda. Python pruža nekoliko načina za čitanje sadržaja datoteke, omogućavajući fleksibilnost u zavisnosti od potreba programa.

#### Učitavanje cjelokupnog sadržaja
Za čitanje kompletnog sadržaja datoteke koristi se metoda `read()`. Ova metoda učitava cijelu datoteku kao jedan tekst (string). Koristi se kada je veličina datoteke dovoljno mala da se može smjestiti u memoriju.

```python=
with open("primjer.txt", "r") as datoteka:
    sadrzaj = datoteka.read()
    print(sadrzaj)
```

> Sadržaj datoteke `primjer.txt` biće prikazan kao jedan kontinuirani tekst.

#### Čitanje svih linija odjednom
Metoda `readlines()` učitava sve linije iz datoteke i vraća ih kao listu stringova. Svaka linija u datoteci predstavlja jedan element liste.

```python=
with open("primjer.txt", "r") as datoteka:
    linije = datoteka.readlines()
    for linija in linije:
        print(linija)
```

> Sve linije biće prikazane redom, sa uklonjenim prelazima na novu liniju.

Kao i metoda `read()`, `readlines()` je pogodna za manje datoteke, jer učitava cijeli sadržaj u memoriju.

#### Čitanje liniju po liniju
Za učitavanje sadržaja datoteke liniju po liniju koristi se metoda `readline()`. Ova metoda učitava jednu liniju iz datoteke svaki put kada se pozove, te svaki naredni put čita iduću liniju.

```python=
with open("primjer.txt", "r") as datoteka:
    linija = datoteka.readline()
    while linija:
        print(linija)
        linija = datoteka.readline()
```

> Svaka linija datoteke biće ispisana na ekranu, jedna po jedna.

U kodu iznad, učitava se prva linija fajla, te se svaka naredna linija čita kroz `while` petlju. Petlja se prekida kada učitana linija bude prazna, jer tada uslov `while` petlje bude nezadovoljen.

#### Iteracija kroz linije datoteke
Datoteka se može tretirati kao *iterabilni objekt* (moguće je koristiti petlju za prolazak kroz sve elemente), što omogućava direktnu iteraciju kroz njene linije u petlji `for`. Ovo je efikasniji i čitljiviji način za čitanje linija iz datoteke.

```python=
with open("primjer.txt", "r") as datoteka:
    for linija in datoteka:
        print(linija)
```

> Linije datoteke `primjer.txt` biće redom prikazane na ekranu.

#### Čitanje određenog broja karaktera
Za čitanje ograničenog broja karaktera koristi se metoda `read(n)`, gdje je `n` broj karaktera koji se učitavaju odjednom. Ovo je korisno za rad sa velikim datotekama ili binarnim podacima.

```python=
with open("primjer.txt", "r") as datoteka:
    dio_sadrzaja = datoteka.read(10)
    print(dio_sadrzaja)
```

> Prvih 10 karaktera datoteke biće prikazano na ekranu.

Metoda `read()` može se pozivati više puta za uzastopno čitanje različitih dijelova datoteke.

Svaka od ovih metoda omogućava različite pristupe radu sa datotekama, pružajući fleksibilnost u zavisnosti od veličine datoteke i specifičnih zahtjeva programa.


:::info
#### Koji način izabrati?
Za čitanje datoteka, odabir odgovarajuće metode zavisi od njihove veličine i memorijskih ograničenja programa. Kod manjih datoteka, gdje cijeli sadržaj može stati u memoriju, metode poput `read()` i `readlines()` su prikladne. Metoda `read()` omogućava učitavanje cijelog sadržaja datoteke kao jednog stringa, dok `readlines()` vraća sve linije u obliku liste. Prednosti ovih metoda su jednostavnost upotrebe i pogodnost za obradu cjelokupnog sadržaja odjednom, dok su glavni nedostatak problemi sa memorijom kada se radi o velikim datotekama.

Za veće datoteke, gdje nije praktično učitati cijeli sadržaj odjednom, prednost se daje postupnim tehnikama. Metoda `readline()` omogućava čitanje jedne linije po pozivu, čime se minimizira potrošnja memorije, dok iteracija kroz datoteku korištenjem `for` petlje omogućava jednostavan i efikasan način za obradu linija jednu po jednu. Alternativno, metoda `read(n)` koristi se za čitanje dijelova sadržaja određene veličine, pružajući veću kontrolu nad procesom. Ove metode su efikasnije za velike datoteke, ali često zahtijevaju dodatnu logiku za praćenje obrade. 

Prilikom izbora metode, potrebno je balansirati između upotrebe memorije i složenosti implementacije kako bi se postigla optimalna efikasnost.
:::

### Pisanje u datoteke

Pisanje u datoteke omogućava trajno skladištenje podataka proizvedenih tokom izvršavanja programa. U Pythonu se za ovu svrhu koristi funkcija `open()` sa režimima rada koji omogućavaju zapisivanje ili dodavanje podataka. Proces zapisivanja podataka zahtijeva pažljivo upravljanje datotekama kako bi se osiguralo da podaci budu pravilno pohranjeni i da ne dođe do prepisivanja važnih informacija.

#### Otvaranje datoteke za pisanje
Za zapisivanje podataka u datoteku koristi se režim **`w`**. Ovaj režim kreira novu datoteku ako ona ne postoji ili briše sadržaj postojeće datoteke prije zapisivanja.

```python=
# Pisanje u datoteku koristeći režim 'w'
with open("primjer.txt", "w") as datoteka:
    datoteka.write("Ovo je prvi red.\n")
    datoteka.write("Ovo je drugi red.\n")
```

> Datoteka `primjer.txt` biće kreirana (ili prepisana) i sadržaće dva reda teksta.

Pri pisanju u datoteku korištenjem metode `write()`, posebno je važno eksplicitno dodati znak za novi red (`\n`) nakon svakog reda koji treba završiti. Pythonova metoda `write()` ne dodaje automatski prelaz na novu liniju, zbog čega svi unosi bez ovog znaka ostaju u istom redu. Na primjer, bez dodavanja `\n`, više poziva metode `write()` rezultiraće spajanjem teksta u jednom kontinuiranom nizu. Znak za novi red osigurava pravilno formatiranje sadržaja u datoteci, čineći ga lakše čitljivim i organizovanim za buduću upotrebu. Isto vrijedi za sve primjere u kojima je naveden znak za novi red.

#### Dodavanje sadržaja u datoteku
Ako je potrebno zadržati postojeći sadržaj datoteke i dodati nove podatke, koristi se režim **`a`** (*append*). Ovaj režim omogućava dodavanje podataka na kraj datoteke bez njenog brisanja.

```python=
# Dodavanje teksta u postojeću datoteku
with open("primjer.txt", "a") as datoteka:
    datoteka.write("Ovo je novi red dodan na kraj.\n")
```

> Novi red će biti dodan na kraj datoteke `primjer.txt`, bez brisanja postojećeg sadržaja.

#### Pisanje u binarne datoteke
Za rad sa binarnim datotekama koristi se kombinacija režima za pisanje ili dodavanje sa slovom **`b`** (npr. `wb`, `ab`). Ove datoteke zahtijevaju zapisivanje podataka u binarnom formatu.

```python=
# Pisanje binarnih podataka u datoteku
with open("primjer.bin", "wb") as datoteka:
    datoteka.write(b"Ovo su binarni podaci.\n")
```

> Datoteka `primjer.bin` će sadržavati binarne podatke.

U primjeru iznad, režim `wb` koristi se za pisanje binarnih podataka u datoteku. Kada se datoteka otvori u ovom režimu, svi podaci koji se zapisuju moraju biti predstavljeni kao **bajtovi** (engl. *bytes*), a ne obični stringovi.

Prefiks `b` ispred stringa, kao što je `b"Ovo su binarni podaci.\n"`, označava da je string kodiran kao niz bajtova. To znači da se svaki karakter iz stringa prevodi u njegov odgovarajući bajtni oblik, čime se omogućava rad s podacima na nivou nižem od ljudski čitljivog teksta. 

Ovaj pristup je posebno koristan za rad s formatima poput slika, videozapisa, audio datoteka ili drugih binarnih podataka koji zahtijevaju precizno očuvanje originalnog formata bez konverzije u tekst.

#### Pisanje više linija odjednom
Za zapisivanje više linija u datoteku odjednom koristi se metoda `writelines()`, koja prima listu stringova. Svaki string predstavlja jedan red koji će biti zapisan u datoteku.

```python=
# Pisanje više linija odjednom
linije = ["Prvi red.\n", "Drugi red.\n", "Treći red.\n"]

with open("primjer.txt", "w") as datoteka:
    datoteka.writelines(linije)
```

> Datoteka `primjer.txt` će sadržavati tri linije navedene u listi `linije`.

## Kombinovani režimi otvaranja datoteka

Kako je ranije navedeno, korištenje funkcije `open()` uz odgovarajući **režim otvaranja** definiše da li će se datoteka čitati, pisati, dodavati ili obrađivati u binarnom formatu. Ispravan izbor režima ključan je za pravilno upravljanje datotekama i sprečavanje potencijalnog gubitka podataka. Tabelarni prikaz osnovnih režima otvaranja datoteka naveden je ispod.   

| Režim  | Opis                                                                 | Primjer korištenja                         |  
|--------|----------------------------------------------------------------------|-------------------------------------------|  
| `r`    | Otvara datoteku za **čitanje**. Ako datoteka ne postoji, javlja se greška (`FileNotFoundError`). | `open("primjer.txt", "r")`                 |  
| `w`    | Otvara datoteku za **pisanje**. Ako datoteka već postoji, njen sadržaj se briše. Ako ne postoji, kreira se nova. | `open("primjer.txt", "w")`                 |  
| `a`    | Otvara datoteku za **dodavanje** sadržaja na kraj. Ako ne postoji, kreira se nova datoteka.  | `open("primjer.txt", "a")`                 |  
| `b`    | Koristi se za **binarne datoteke** u kombinaciji s drugim režimima (`rb`, `wb`, `ab`).          | `open("slika.jpg", "rb")`                  |  

Posebnu grupu režima čine kombinovani režimi, navedeni u tabeli ispod.


| Režim  | Opis                                                                 | Primjer korištenja                         |  
|--------|----------------------------------------------------------------------|-------------------------------------------|  
| `r+`   | Otvara datoteku za **čitanje i pisanje**. Ne briše postojeći sadržaj. Ako datoteka ne postoji, javlja se greška. | `open("primjer.txt", "r+")`                |  
| `w+`   | Otvara datoteku za **čitanje i pisanje**. Briše postojeći sadržaj ili kreira novu datoteku. | `open("primjer.txt", "w+")`                |  
| `a+`   | Otvara datoteku za **dodavanje i čitanje**. Kreira novu datoteku ako ne postoji. Pisanje uvijek dodaje na kraj. | `open("primjer.txt", "a+")`                |  
| `x`    | Kreira novu datoteku za **pisanje**. Ako datoteka već postoji, javlja se greška (`FileExistsError`). | `open("primjer.txt", "x")`                 |  

### Detaljnije o kombinovanim režimima  

- **`r+` (čitanje i pisanje):**  
  Ovaj režim omogućava čitanje i pisanje u istoj datoteci bez brisanja postojećeg sadržaja. Kursor se postavlja na početak datoteke, što znači da novo pisanje može prebrisati postojeće podatke. Pogodan je za situacije kada je potrebno ažurirati određeni dio datoteke.  

  ```python=  
  with open("primjer.txt", "r+") as datoteka:  
      sadrzaj = datoteka.read()  
      datoteka.write("\nDodaj novi red.")  # Dodaje na kraj nakon čitanja  
  ```  

- **`w+` (brisanje i pisanje s čitanjem):**  
  Koristi se kada je potrebno ponovo kreirati datoteku, ali uz mogućnost čitanja podataka odmah nakon pisanja. Ako datoteka već postoji, njen sadržaj se briše.  

  ```python=  
  with open("primjer.txt", "w+") as datoteka:  
      datoteka.write("Prvi red podataka.")  
      datoteka.seek(0)  # Vraća na početak datoteke  
      print(datoteka.read())  
  ```  

- **`a+` (dodavanje i čitanje):**  
  Ovaj režim omogućava dodavanje podataka na kraj datoteke uz istovremenu mogućnost čitanja. Ako datoteka ne postoji, kreira se nova. Pogodan je za log datoteke ili evidenciju podataka gdje je važno sačuvati raniji sadržaj.  

  ```python=  
  with open("log.txt", "a+") as datoteka:  
      datoteka.write("Novi unos u log.\n")  
      datoteka.seek(0)  # Omogućava čitanje od početka  
      print(datoteka.read())  
  ```  

- **`x` (kreiranje nove datoteke):**  
  Režim `x` koristi se isključivo za kreiranje nove datoteke. Ako datoteka s istim nazivom već postoji, Python generiše grešku. Ovaj režim je koristan za situacije kada je važno osigurati da ne dođe do prepisivanja postojećih podataka.  

  ```python=  
  with open("novi_fajl.txt", "x") as datoteka:  
      datoteka.write("Ovo je novi fajl.")  
  ```  

## Upravljanje greškama prilikom rada s datotekama

Tokom rada s datotekama, greške se mogu javiti iz različitih razloga, kao što su nedostatak dozvola za pristup datoteci, nepostojanje datoteke, problemi sa diskom ili neočekivane situacije u sistemu. Kako bi se spriječilo da ove greške prekinu rad programa, Python omogućava upravljanje greškama korištenjem strukture `try-except`. Ovaj pristup omogućava programerima da detektuju i obrade greške na kontrolisan način.

### Struktura `try-except`
Osnovna struktura `try-except` omogućava izvršavanje koda unutar bloka `try`. Ako se greška dogodi tokom izvršavanja, Python preusmjerava tok programa na odgovarajući blok `except`, gdje se greška može obraditi.

```python=
# Osnovna struktura try-except
try:
    # Kod koji može izazvati grešku
    with open("nepostojeca_datoteka.txt", "r") as datoteka:
        sadrzaj = datoteka.read()
except FileNotFoundError:
    # Obrada greške
    print("Datoteka ne postoji. Provjerite naziv ili putanju.")
```

> Ako datoteka ne postoji, program neće prekinuti izvršavanje, već će prikazati poruku korisniku.

#### Višestruki blokovi `except`
Ako postoji mogućnost različitih tipova grešaka, moguće je koristiti više blokova `except` za obradu svakog tipa greške posebno.

```python=
try:
    with open("primjer.txt", "r") as datoteka:
        sadrzaj = datoteka.read()
except FileNotFoundError:
    print("Greška: Datoteka nije pronađena.")
except PermissionError:
    print("Greška: Nemate dozvolu za pristup datoteci.")
except Exception as e:
    print(f"Nepoznata greška: {e}")
```

> Ovaj primjer obrađuje greške specifične za rad s datotekama, dok generalni blok `except` pokriva sve ostale nepredviđene greške.

#### Korištenje bloka `else`
Ako se kod unutar `try` bloka izvrši bez grešaka, moguće je dodati blok `else`, koji će se izvršiti nakon uspješnog izvršavanja.

```python=
try:
    with open("primjer.txt", "r") as datoteka:
        sadrzaj = datoteka.read()
except FileNotFoundError:
    print("Greška: Datoteka nije pronađena.")
else:
    print("Datoteka je uspješno pročitana:")
    print(sadrzaj)
```

> Blok `else` omogućava dodatnu logiku koja zavisi od uspješnog izvršavanja operacije.

#### Korištenje bloka `finally`
Blok `finally` se uvijek izvršava, bez obzira na to da li je greška nastala ili ne. Ovo je korisno za zadatke kao što su oslobađanje resursa ili zapisivanje završnih informacija.

```python=
try:
    with open("primjer.txt", "r") as datoteka:
        sadrzaj = datoteka.read()
except FileNotFoundError:
    print("Greška: Datoteka nije pronađena.")
finally:
    print("Završena obrada datoteke.")
```

> Ovaj blok je posebno koristan za čišćenje resursa ili obavljanje aktivnosti koje moraju biti izvršene bez obzira na greške.

#### Prednosti `try-except` strukture
- **Kontrolisano rukovanje greškama**: Program ne prekida rad zbog neočekivanih problema.
- **Informativni izlaz za korisnika**: Greške se mogu objasniti na razumljiv način.
- **Fleksibilnost u rukovanju različitim greškama**: Višestruki blokovi `except` omogućavaju preciznu obradu specifičnih situacija.

Dodavanjem `try-except` strukture, programi postaju robusniji i prilagodljiviji realnim uslovima, gdje se greške mogu pojaviti. Ovaj pristup se preporučuje za sve kritične operacije, uključujući rad s datotekama.

:::info
#### Savjeti za pisanje u datoteke
1. **Pažljivo odabrati režim rada**: Korištenje režima `w` briše sav postojeći sadržaj datoteke. Ako je potrebno sačuvati postojeće podatke, koristi se režim `a`.
2. **Osigurati ispravno zatvaranje datoteke**: Korištenje kontekstnog menadžera `with` osigurava automatsko zatvaranje datoteke nakon završetka rada.
3. **Koristiti `try-except` za hvatanje grešaka**: Ovo je korisno za upravljanje neočekivanim problemima tokom zapisivanja.

Pisanje podataka u datoteke omogućava stvaranje trajnih zapisa, bilo da se radi o tekstualnim podacima ili binarnim formatima. Odabir odgovarajuće metode zapisivanja zavisi od prirode podataka i potreba aplikacije.
:::

## Sažetak  

Rad sa datotekama predstavlja temeljnu vještinu u razvoju softverskih aplikacija, omogućavajući trajno skladištenje podataka i njihovu ponovnu upotrebu. Razumijevanje razlike između privremenih podataka, pohranjenih u radnoj memoriji, i trajnih podataka na čvrstom disku ključno je za izgradnju robusnih i efikasnih rješenja.  

Korištenjem osnovnih operacija – otvaranja, čitanja, pisanja i zatvaranja datoteka – programi mogu upravljati velikim količinama informacija, unaprijediti korisničko iskustvo i osigurati integritet podataka. Rad sa tekstualnim i binarnim datotekama omogućava široku primjenu, od jednostavnih aplikacija do kompleksnih sistema za analizu i skladištenje podataka.  

Važan aspekt rada s datotekama je razumijevanje različitih režima otvaranja datoteka (`r`, `w`, `a`, `b`) i njihovih kombinacija, koji određuju način interakcije sa sadržajem. Ispravan izbor režima ključan je za zaštitu podataka i sprječavanje nenamjernog brisanja ili prepisivanja postojećih informacija. Opcije poput `r+` (čitanje i pisanje) i `wb` (pisanje binarnih podataka) omogućavaju dodatnu fleksibilnost, dok režim `a` omogućava dodavanje novih podataka bez gubitka postojećeg sadržaja. Poznavanje ovih režima osigurava efikasno upravljanje različitim vrstama datoteka i unapređuje stabilnost aplikacija.  

Posebno je važno usvojiti dobre prakse prilikom rada sa datotekama, poput korištenja kontekstnog menadžera `with` za automatsko zatvaranje datoteka i implementacije `try-except` strukture za rukovanje greškama. Ovi pristupi osiguravaju stabilnost aplikacija, minimiziraju rizik od gubitka podataka i doprinose efikasnijem upravljanju resursima.  

Bez obzira na to da li se radi o malim skriptama ili velikim aplikacijama, pravilno korištenje datoteka ključ je za stvaranje pouzdanih, funkcionalnih i dugotrajnih softverskih rješenja.