Ciele kapitoly: oboznámiť sa s triedou File a jej základnými metódami. Práca s adresármi a súbormi. Čítanie zo súboru a zapisovanie do súboru. Vstup z klávesnice. Základné typy prúdov. Bufferovanie.
Trieda
File umožňuje základnú prácu s adresármi a súbormi. Je triedou balíka
java.io. Pozrime si prácu niektorých
jej metód na príklade. V nasledujúcom kóde uvidíme príklad týchto činností:
1. Zistíme si meno aktuálneho adresára.
2. Vytvoríme nový podadresár.
3. Dáme si vymenovať jeho podsúbory a
podadresáre
4. V podadresári vytvoríme nový súbor.
(Nebudeme doňho písať, to trieda File nedokáže.)
5. Zistíme, či v podadresári existuje súbor
„help.txt“.
6. Premenujeme súbor v podadresári.
7. Vytvoríme nové adresáre po ceste „
C:\Anicka\mam\ta\rad” .
import
java.io.*;
public
class Subory{
public static void main(String[]
args){
//1. Zistime si meno aktualneho adresara.
String menoAktAdresara =
System.getProperty("user.dir");
System.out.println("Meno
aktualneho adresara je: " + menoAktAdresara);
//2. Vytvorime novy podadresar.
//
najprv musime vytvorit instanciu triedy File
File podadresar = new
File("novyPodadresar");
// existuje v aktualnom adresari adresar
alebo subor s tymto menom?
System.out.println(" novyPodadresar
existuje = " + podadresar.exists());
// teraz ho vytvorime
podadresar.mkdir();
// zistime, ci existuje
System.out.println(" novyPodadresar
existuje = " + podadresar.exists());
//3. Dame vymenovat subory a podadresare v
aktualnom adresari ako Stringy.
//
najprv musime vytvorit instanciu triedy File pre aktualny adresar
File aktAdresar = new File(menoAktAdresara);
String[] names = aktAdresar.list();
System.out.println("Aktualny adresar
obsahuje: ");
for(int i = 0; i < names.length; i++){
System.out.println(names[i]);
}
// mozme ziskat aj zoznam suborov a
adresarov ako pole typu File
File[] subory = aktAdresar.listFiles();
for(int i = 0; i < subory.length; i++){
System.out.println(subory[i].getName() +
" absolutna cesta: " +
subory[i].getAbsolutePath());
}
//4. V podadresari vytvorime nový súbor.
File
suborcek = new File(podadresar,"suborcek.txt");
//System.out.println("V
podadresari je subor: " + (podadresar.list())[0]); - chyba
//
najprv treba subor vytvorit
try{
suborcek.createNewFile();
}
catch(IOException
e){
System.out.println("Chyba
pri tvoreni suboru.");
}
System.out.println("V
podadresari je subor: " + (podadresar.list())[0]);
//5. Zistíme, ci v podadresári existuje súbor
"help.txt".
File
tenHelp = new File(podadresar,"help.txt");
System.out.println("
V podadresari " + podadresar + " Existuje subor help.txt " + tenHelp.exists());
//6. Premenujeme súbor v podadresári.
//
takto to nejde: suborcek.renameTo("premenovany.subor");
File nahradny = new File(podadresar,"premenovany.subor");
suborcek.renameTo(nahradny);
//7.
vytvorime nove adresare
//
najprv si nachystame cestu
String
s = File.separator;
String
cesta = "C:" + s + "Anicka" + s + "mam" + s +
"ta" + s + "rad";
File
celaCesta = new File(cesta);
System.out.println("Adresar
" + cesta + " existuje =
" + celaCesta.exists());
celaCesta.mkdirs();
System.out.println("Adresar
" + cesta + " existuje =
" + celaCesta.exists());
}
}
Jeden
možný výstup:
Meno
aktualneho adresara je: D:\Ivan\Java\vyuc 8
novyPodadresar existuje = false
novyPodadresar existuje = true
Aktualny
adresar obsahuje:
novyPodadresar
Subory.class
Subory.java
vyuc
8.kawa
novyPodadresar absolutna cesta: D:\Ivan\Java\vyuc
8\novyPodadresar
Subory.class absolutna cesta: D:\Ivan\Java\vyuc
8\Subory.class
Subory.java absolutna cesta: D:\Ivan\Java\vyuc
8\Subory.java
vyuc
8.kawa absolutna cesta:
D:\Ivan\Java\vyuc 8\vyuc 8.kawa
V
podadresari je subor: premenovany.subor
V podadresari novyPodadresar Existuje
subor help.txt false
Adresar
C:\Anicka\mam\ta\rad existuje = false
Adresar
C:\Anicka\mam\ta\rad existuje = true
Process
Exit...
V kóde sme použili statickú premennú triedy File typu String: File.separator (vo
Windowsoch je
to
„\“). Všimnite si rozdiel pri práci
metód „mkdir()“ a „mkdirs()“. Prvá vytvorí len jeden adresár, druhá všetky
adresáre, vymenované na danej ceste. Všetky potrebné detaily ku metódam,
používaným v kóde sa dajú nájsť v dokumentácii triedy File. Metódy list() a listFiles() majú aj svoje preťažené
varianty s argumentom typu FilenameFilter. FilenameFilter je rozhranie, ktoré
po implementovaní umožní metódam list() a listFiles() vypísať len tie súbory,
ktoré spĺňajú určité kritériá. Tie, ktoré sme nastavili pomocou inštancie typu
FilenameFilter a jej metódy „accept“. Ďalšie detaily – znova v dokumentácii
rozhrania FilenameFilter.
Termín „prúd dát“ sa v Jave používa na
označenie vstupu-výstupu. Každý prúd dát je systémom pripojený na nejaké
fyzické zariadenie vstupu alebo výstupu, poprípade na pamäť patriacu nejakému
objektu (napr. vláknu) , programu, či
na údaje obsiahnuté v súbore, alebo uskladnené niekde na sieti. Java implementuje prúdy dát v balíku
java.io.
V jave existujú dva základné typy prúdov:
Znakovo
orientované prúdy – základná jednotka dát je 16-bitová pre znaky Unicode. Základné
abstraktné triedy, slúžiace na vytváranie takýchto prúdov sú triedy Reader
a Writer.
Bajtovo
orientované prúdy – odvodené od abstraktných tried InputStream a OutputStream.
Napríklad „System.out “ je statický člen
triedy „System“, ktorý je typu PrintStream . PrintStream je trieda , dediaca od
triedy java.io.FilterOutputStream a táto je už priamym potomkom abstraktnej
triedy java.io.OutputStream.
Od
štyroch abstraktných tried Reader, Writer, InputStream a OutputStream je odvodených množstvo špecializovaných
podtried. My si nižšie uvedieme len niektoré z nich. Vymenujme ale metódy,
ktoré všetky tieto triedy – potomkovia zdedia. Všetky vymenované metódy môžu
vyvolať výnimku typu IOException.
Trieda Writer:
void write(int i)
void write(char[] poleZnakov)
void write(char[] poleZnakov. int index, int pocetZnakov)
Pozrime sa na príklad čítania a písania po
znakoch. Nasledujúci kód pracuje
správne, ak je súbor „Prepisuj.java“
a takisto „text.txt“ v aktuálnom adresári.
import
java.io.*;
public
class Prepisuj {
// prepise text zo suboru "text.txt"
tak, ze vsetky pismena "y"
// zameni za "i"
char
totoPrepis;
char
prepisNaToto;
public
Prepisuj(char zTohto, char naTento){
totoPrepis = zTohto;
prepisNaToto = naTento;
}
public
void prepis(File vzor, File ciel){
try{
FileReader citac = new
FileReader(vzor);
FileWriter pis = new FileWriter(ciel);
int c;
while(( c = citac.read()) != -1 ){
if(c==totoPrepis)
pis.write(prepisNaToto);
else
pis.write(c);
}
citac.close();
pis.close();
}
catch(FileNotFoundException fe){
System.err.println("Nenasiel som subor.");
}
catch(IOException e){
System.err.println("Chyba pri
tvoreni FileWritera.");
}
}
public static void main(String[] args){
File vzor = new File("text.txt");
File
ciel = new File("prepisanyText.txt");
Prepisuj
zmen = new Prepisuj('y', 'i');
zmen.prepis(vzor,ciel);
}//EOMain
}//EOClass
Možný
výstup:
Ak súbor text.txt existoval v aktuálnom
adresári a bol v ňom tento text:
Tento
nevyznamny text je urceny na to, aby bol prepisany.
Cierny ponik cierni poniklec. Styri psy sa
potkli o kly.
Jary
basnik basni o jari, mozno sa mu aj rym podari.
Teraz
skúsim písať aj ľščťžýáíé.
Výsledkom
programu bolo vytvorenie súboru s názvom „prepisanyText.txt“
A
s textom:
Tento
neviznamni text je urceni na to, abi bol prepisani.
Cierni ponik cierni poniklec. Stiri psi sa
potkli o kli.
Jari
basnik basni o jari, mozno sa mu aj rim podari.
Teraz
skúsim písa? aj ľšč?žýáíé.
Ako
vidíme, Java si tu neporadila so všetkými písmenami slovenskej abecedy.Program bol spustený pod verziou Java 1.3. Pri spustení vo verzii 1.4 sa správne zapísal aj znak " ť ".
Všimnime si, že metóda „read()“
vracia integer. Ak sa dosiahol koniec prúdu – v tomto prípade koniec súboru –
vráti hodnotu –1. Pozrite si v
dokumentácii, s akými argumentami je schopná pracovať metóda „write()“.
Pre vyspelého čitateľa nie je zrovna ideálne riešenie môcť čítať iba znak po znaku. Aby sme mohli čítať po celých riadkoch, stačí nám už známe objekty typu „FileReader, FileWriter“ obaliť objektami typu „BufferedReader, BufferedWriter“, ktoré majú k dispozícii metódy „readLine()“, respektíve
„write(String s) “ a „newLine()“. Rozviňme tému z predchádzajúceho príkladu. Pozrime si prácu programu Cenzor, ktorý z načítaného súboru „list.txt“ vyberie nepovolené slová a nahradí ich jemnejšími.
Kód P8.3
import java.io.*;
public class Cenzor {
String[] zakazane;
String[] nahradne;
public Cenzor(String[] zle, String[] dobre) {
if(zle.length > dobre.length)
System.err.println("Cenzor zle vytvoreny.");
else {
zakazane = zle;
nahradne = dobre;
}
}
public void cenzuruj(File f){
try{
FileReader fr = new FileReader(f);
BufferedReader citaj = new BufferedReader(fr);
File scenzurovane = new File("pozdrav.txt");
scenzurovane.createNewFile();
BufferedWriter pis = new BufferedWriter(new FileWriter(scenzurovane));
String s, sc;
while( (s = citaj.readLine())!= null) {
sc = oprav(s);
pis.write(sc);
pis.newLine();
}
fr.close();
pis.close();
}
catch(IOException e){
System.err.println("Sorry, chyba pri cenzure.");
}
}
public String oprav(String s){
String sc;
sc = s;
// pre kazdy prvok - zakazane slovo nahradi toto slovo povolenym
for(int j = 0; j < zakazane.length; j++){
int index;
int k = zakazane[j].length();
while((index =sc.indexOf(zakazane[j])) > -1){
// tu zakazane slovo vyreze a nahradi ho nahradnym
sc = sc.substring(0,index) + nahradne[j] + sc.substring(index +k);
}
} //EOFor
return sc;
}//EOOprav
public static void main(String[] args){
Cenzor catar = new Cenzor(new String[]{"zle","idiot"}, new String[]{"dobre","sympaticky"});
File f = new File("list.txt");
catar.cenzuruj(f);
}
}
Program sme spustili so súborom „list.txt“ v aktuálnom adresári, ktorý mal tento text:
Mili rodicia,
mam sa tu na
vojne velmi zle. Aj nam velmi zle varia.
Navyse catar
je idiot, porucik tiez a snad o ziadnom nadriadenom
by som nemohol
povedat, ze nie je idiot. No, ale vsetkemu zlemu
je po case
koniec. Coskoro budem z tohto idiotskeho prostredia
zase doma.
Vas Karol
Program vytvoril súbor „pozdrav.txt“ s textom:
Mili rodicia,
mam sa tu na
vojne velmi dobre. Aj nam velmi dobre varia.
Navyse catar
je sympaticky, porucik tiez a snad o ziadnom nadriadenom
by som nemohol
povedat, ze nie je sympaticky. No, ale vsetkemu dobremu
je po case
koniec. Coskoro budem z tohto sympatickyskeho prostredia
zase doma.
Vas Karol
Ukladanie objektov. ObjectInputStream,
ObjectOutputStream
Java umožňuje ukladať na disk aj konkrétne inštancie tried, t. j. konkrétne objekty. A to takým spôsobom, aby sa zachovali, aj keď program skončí a aby boli k dispozícii pri ďalších spusteniach tohto programu alebo iných programov. Tento proces sa nazýva serializácia a vykonáva sa prostredníctvom tried ObjectInputStream a ObjectOutputStream. Majú okrem iného k dispozícii metódy readObject(), respektíve writeObject().
Použijeme kód P5.6 Vstup.class dajte do spoločného adresára so súborom Pokec.java, obsahujúcim nasledujúci kód:
Kód P8.4
import java.io.*;
class Besednik implements Serializable{
int vek = -1;
String meno = "?";
Boolean jeMuz =
null;
public void setVek(int j ){
vek = j;
}
public Besednik(int vek, String meno, boolean jeMuz){
this.vek = vek;
this.meno = meno;
this.jeMuz = new Boolean(jeMuz);
}
// nasledujuci konstruktor sluzi pre spolupracu
// s metodou nacitaj() v triede Pokec
public Besednik(){
this.meno = "Nacitanie prebehlo zle, neviem urcit udaje o Besednikovi";
}
public void setMeno(String name){
meno = name;
}
public void setPohlavie(String s){
if(s.equals("ano")) jeMuz = new Boolean(true);
else {
if(s.equals("nie")) jeMuz = new Boolean(false);
else System.err.println("Z tohto udaju neviem urcit pohlavie.");
}//EOVonkajsieElse
}//EOMethod
public String toString(){
String s = meno;
if(jeMuz != null){
boolean muz = jeMuz.booleanValue();
if(muz) {
s += " je muz ";
}
else
{
s+= " je zena ";
}
}
if(vek != -1){
s+= " vo veku " + String.valueOf(vek) + " rokov";
}
s+=".";
return s;
}
}
public class Pokec {
public void rozhovor(Besednik bes){
System.out.println("Napis prosim tvoje meno a stlac enter.");
bes.setMeno( Vstup.citaj());
System.out.println("Napis prosim svoj vek. Cislom.");
int kolkoRokov = Integer.parseInt(Vstup.citaj());
bes.setVek(kolkoRokov);
System.out.println("Si muz? Odpovedz prosim \"ano\" alebo \"nie\".");
bes.setPohlavie(Vstup.citaj());
}
// tato metoda vrati objekt Besednik po precitani suboru
public Besednik nacitaj(File f){
Besednik vzkrieseny = new Besednik();
try{
FileInputStream in = new FileInputStream(f);
ObjectInputStream vzkriesObjekt = new ObjectInputStream(in);
// moze sposobit ClassNotFoundException:
vzkrieseny = (Besednik)vzkriesObjekt.readObject();
}
catch(IOException e){
System.err.println("Problemy pri krieseni ulozeneho Besednika.");
}
catch(ClassNotFoundException cnf){
System.err.println("Zial, Besednici uz neexistuju.");
}
return vzkrieseny;
}
public void uloz(Besednik bes){
File cakaren = new File("cakaren.bin");
try{
if(! (cakaren.exists() && cakaren.isFile()) ){
cakaren.createNewFile();
}
FileOutputStream out = new FileOutputStream(cakaren);
ObjectOutputStream zapisObjekt = new ObjectOutputStream(out);
zapisObjekt.writeObject(bes);
out.close();
}//EOTry
catch(IOException e){
System.err.println("Chyba pri ukladani Besednika");
}
}//EndOfUloz
public static void main(String[] args){
Pokec skladnik = new Pokec();
Besednik prvyClovek = new Besednik(0,"Adam",true);
// ak uz udaje o osobe existuju, nacitaj ich zo suboru cakaren.bin
File cakaren = new File("cakaren.bin");
if(cakaren.exists() && cakaren.isFile()){
prvyClovek = skladnik.nacitaj(cakaren);
System.out.println(prvyClovek);
}
// ak nie, prvyClovek ostava az do rozhovoru nemeneny
// Nacita udaje z klavesnice a nastavi nove hodnoty do objektu Besednik
skladnik.rozhovor(prvyClovek);
System.out.println(prvyClovek + "\n Ukladam Besednika pre dalsi beh programu.");
skladnik.uloz(prvyClovek);
// objekt Besednik ulozi do suboru cakaren.bin
}
}
Jedna možnosť výpisov z programu:
Prvý beh programu:
Napis prosim tvoje meno a stlac enter.
Kapitan Nemo
Napis prosim svoj vek. Cislom.
84
Si muz? Odpovedz prosim "ano" alebo
"nie".
ano
Kapitan Nemo je muz
vo veku 84 rokov.
Ukladam Besednika pre dalsi beh programu.
Process Exit...
Druhý beh programu:
Kapitan Nemo je muz
vo veku 84 rokov.
Napis prosim tvoje meno a stisni enter.
Martanka Ovo
Napis prosim svoj vek. Cislom.
564
Si muz? Odpovedz prosim "ano" alebo
"nie".
nie
Martanka Ovo je zena vo veku 564 rokov.
Ukladam
Besednika pre dalsi beh programu.
Process Exit...
a)V
kóde P8.1 nahraďte riadok
File
nahradny = new File(podadresar,"premenovany.subor");
riadkom
File
nahradny = new File("premenovany.subor");
Spustite
program znovu. Preskúmajte po jeho zbehnutí aktuálny adresár a jeho podadresár.
Čo sa stalo, zmenilo?
b)
Skúste premenovať adresár „mam“ z cesty C:\Anicka\mam\ta\rad na „nemam“.
Zvoľte
si dostatočne plný adresár - napríklad C:\Program Files. V aktuálnom adresári
vytvorte súbor „spion.txt“ . Do tohto súboru vypíšte všetky podadresáre a
súbory obsiahnuté vo zvolenom adresári. Pri každom z nich vypíšte aj jeho
veľkosť.
Cv8.3
Vráťte sa znovu ku kódu P5.6. Preskúmajte ho z hľadiska toho, čo už viete
o ošetrovaní výnimiek a o metódach vstupu a výstupu.
Prerobte tento program tak, aby metóda „read()“ čítala z klávesnice len
jednotlivé znaky – pozrite sa v dokumentácii, do akej triedy patrí objekt
System.in a aké varianty metódy „read()“ môže používať.
Cv8.1
b)
Napriklad takto: Dopíšte na koniec kódu P8.1
riadky:
File
adresarNaPremenovanie = new File("C:" + s +"Anicka" +s +
"mam");
File
noveMeno = new File("C:" + s +"Anicka" +s +
"nemam");
adresarNaPremenovanie.renameTo(noveMeno);
Spustite
kód a sledujte, čo sa stalo.
Potom
pripíšte ešte jeden riadok:
(r1) adresarNaPremenovanie.delete();
Pozrite
si dokumentáciu k metóde „delete()“, aby ste rozumeli správaniu sa programu.
Nakoniec
nahraďte riadok (r1) týmito riadkami:
celaCesta.delete();
File
adresarTa = new File("C:" + s + "Anicka" + s
+"mam" + s +"ta");
adresarTa.delete();
adresarNaPremenovanie.delete();
Najprv
posledné tri zakomentujte , spustite program a zistite, čo sa stalo s
príslušnými adresármi.
Potom
vždy odkomentujte jeden riadok a zopakujte procedúru. Až kým nebudú všetky
riadky odkomentované.
Vaše komentáre:
kupka@fmph.uniba.sk