Računalništvo 1 (PRA)

lekcije / Datoteke

Datoteke

V tej lekciji se bomo naučili, kako v Javi beremo in pišemo na datoteke.
Kot verjetno vsi vemo, je datoteka zaporedje podatkov, ki so shranjeni na disku ali kakem drugem mediju (CD-ROM, disketa). V datotekah hranimo različne podatke: besedila, preglednice, slike, glasbo, programe, itn.
Vse datoteke, ki so dostopne na računalniku, so organizirane v datotečni sistem (angl. "file system"). To je drevesna struktura, ki sestoji iz direktorijev ali map (angl. "directory"). Direktoriji lahko vsebujejo podmape, ki vsebujejo podmape, itn.
Običajno ima računalnik dostop do večih datotečnih sistemov. Pri operacijskem sistemu Microsoft Windows je vsak datotečni sistem poimenovan s svojo črko. Datotečna sistema A: in B: sta disketi, C: je disk, D: pa je CD-ROM. Če je diskov več, potem je se črkujejo po vrsti C:, D:, E:.
Vsaka datoteka ima ime in stoji v neki mapi. Polno ime datoteke dobimo tako, da zložimo skupaj njeno ime in mapo. Denimo, da je datoteka foo.txt na disku C:, v mapi bla, ki je v podmapi tralala. Potem je polno ime datoteke
C:\tralala\bla\foo.txt
Vidimo, da imena dorektorijev ločimo z znakom \. To velja za Microsoft Windows, medtem ko na Linuxu in Unixu uporabljamo znak /. Kadar pišemo znak \ v Javi v nizu, moramo napisati dvojni \\.
Preden lahko z datoteke beremo ali nanjo pišemo, jo moramo najprej odpreti. Glede na to, ali želimo iz datoteke brati podatke, ali pa vanjo pisati, jo odpremo bodisi za branje bodisi za pisanje.

Branje z datotek

Oglejmo si najprej primer, ko datoteko odpremo za branje. Denimo, da želimo brati z datoteke foo.txt. Ker je Java objektni programski jezik, se datoteko odpre tako, da se preprosto naredi nov objekt ustreznega razreda:
FileReader d = new FileReader("foo.txt");
S tem smo naredili nov objekt d, ki bo sam odprl datoteko foo.txt. Z datoteke lahko nato beremo z metodo read(char[], int, int). V večini primerov želimo brati posamezne vrstice, česar pa metoda read ne omogoča. Zato običajno naredimo še en objekt razreda BufferedReader, ki ga nato uporabljamo za branje posameznih vrstic:
BufferedReader datoteka = new BufferedReader(d);
Objekt datoteka spada v razred BufferedReader, ki vsebuje metodo readLine() za branje ene vrstice. Oglejmo si uporabo datotek v celotnem programu. Napišimo program IzpisiDatoteko.java, ki prebere vrstice dane datoteke in jih izpiše na zaslon:
IzpisiDatoteko.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.io.*;

public class IzpisiDatoteko {
    public static void main(String[] args) throws IOException {

	String ime = args[0];
	
	BufferedReader datoteka = new BufferedReader(new FileReader(ime));

	while(datoteka.ready()) {
	    System.out.println(datoteka.readLine());
	}
	
	datoteka.close();

    }

}
Ne pozabite preizkusiti programa!
Naloga 1
[rešitev]

Pisanje na datoteke

Zdaj pa si še oglejmo, kako pišemo na datoteko. Za pisanje na datoteko bar.txt naredimo objekt razreda FileWriter:
FileWriter d =  new FileWriter("bar.txt");
Tako kot pri branju z datotek je tudi pisanje na datoteko z objektom razreda FileWriter nepraktično. Bolj prikladen je objekt PrintWriter:
PrintWriter datoteka = new PrintWriter(d);
Objekt razreda PrintWriter vsebuje metodi println in print, ki ju že uporabljamo za izpisovanje na zaslon. Sedaj pa jih znamo uporabljati tudi za zapisovanje na datoteke:
ZapisiIzrek.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.io.*;

public class ZapisiIzrek {
    public static void main(String[] args) throws IOException {

	String ime = args[0];
	
	PrintWriter datoteka = new PrintWriter(new FileWriter(ime));

	datoteka.println("Moj najljubsi izrek o trikotnikih je:");
	datoteka.println();
	datoteka.println("Simetrala kota se s simetralo nasprotne stranice");
	datoteka.println("seka na ocrtanem krogu.");	

	datoteka.close();
    }
}
> javac ZapisiIzrek.java
> java ZapisiIzrek poskus.txt
Kam se je zapisal izrek o trikotnikih? Na zaslonu ga ni? Seveda ne, saj smo uporabili metodo println() iz objekta datoteka in ne iz objekta System.out, kot smo to počeli do sedaj. Objekt datoteka je zapisal vse v datoteko poskus.txt.
Opozorilo: zelo pomembno je, da na datoteko zapremo z metodo close(), ko smo končali zapisovanje vanjo, sicer se lahko zgodi, da se podatki ne bodo pravilno zapisali! (Poskusite, kaj se zgodi, če pobrišete ukaz datoteka.close()).
Naloga 2
[rešitev]
Naloga 3
Naloga 4
Naloga 5
Naloga 6
Namig
Napiši program, ki prešteje število besed v dani datoteki. Uporabi metodo prestej_besede iz prejšnje naloge.

Rešitve nalog

Naloga 1

PrestejVrstice.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.io.*;

public class PrestejVrstice {
    public static void main(String[] args) throws IOException {

	String ime = args[0];
	
	BufferedReader datoteka = new BufferedReader(new FileReader(ime));

	int vrstice = 0;

	while(datoteka.ready()) {
	    String neuporabno = datoteka.readLine();
	    vrstice = vrstice + 1;
	}

	System.out.println("Datoteka " + ime + " ima " + vrstice + " vrstic.");

	datoteka.close();
	
    }

}

Naloga 2

Kopiraj.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.io.*;

public class Kopiraj {
    public static void main(String[] args) throws IOException {

	String ime1 = args[0];
	String ime2 = args[1];
	
	BufferedReader dat1 = new BufferedReader(new FileReader(ime1));

	PrintWriter dat2 = new PrintWriter(new FileWriter(ime2));

	while(dat1.ready()) {
	    dat2.println(dat1.readLine());
	}
	
	dat1.close();
	dat2.close();
    }
}