10. praktikum (Vood. Failid)

Teemad

Töötamine failidega. Voogude loomine ja suunamine.

Pärast selle praktikumi läbimist oskab üliõpilane

Failidega töötamiseks vajalikud klassid on koondatud paketti java.io. Selle klassid võimaldavad nii muuta failide sisu kui ka nimetada ümber, kustutada ja luua faile ning katalooge. Failide ja kataloogidega tegelemiseks vajalikud meetodid asuvad klassis File.

// Programm, mis jooksvas kataloogis leiab laiendita failid ja lisab neile laiendi
import java.io.*;
class MuudaFailinimed {
    public static void main(String[] args) {
        try {
            File dir = new File(".");
String[] failid = dir.list();
File vana, uus;
            for (int i = 0; i < failid.length; i++) {
vana = new File(failid[i]);
                if (vana.isFile() && failid[i].indexOf(".") < 0) {
uus = new File(failid[i] + ".txt");
vana.renameTo(uus);
System.out.println("Muudetud "+ vana.getName() + " -> "+ uus.getName());
}
            }
        }
        catch(Exception e) {
            System.out.println("Erind: " + e);
        }
    }
}

Selleks, et muuta failisiseseid andmeid, peame teadma, kuidas toimub andmevahetus failidega. Java andmevahetuse kandvaks mõisteks on voog, mille all mõistetakse suvalist suunatud baidijada. Vooge võib jaotada näiteks vastavalt

Voogudega tegelemiseks on Java API-s üle 60 klassi. Hierarhia tipus asuvad abstraktsed klassid InputStream ja OutputStream, milles on meetodid andmevoost baitide lugemiseks ja nende sinna kirjutamiseks.

Voogudel on reeglina kaks taset, mille määravad voo kasutuseesmärk (ülemine tase) ja kandja (aluspõhi). Sageli on vaja nende ühildamiseks kasutada vahetasemeid.

Voo loomisel tuleb määrata allikas ja arvestada, milline on voo sisu. Samuti tuleb arvestada andmete salvestamise viisi. Näiteks failist baidikaupa lugemiseks võib luua voo 

FileInputStream fin = new FileInputStream("andmed.dat");

Failidega tegelevate voogude konstruktorites on faili määramiseks võimalik kasutada klassi File.

//Programm, mis teeb koopia etteantud failist:

import java.io.*;

class KopeeriFail {

    public  static void main(String[] args) {

        try {

            InputStream sisse = new FileInputStream(new File(args[0]));

            OutputStream välja = new FileOutputStream(new File(args[0] + ".copy"));

            byte[] buf = new byte[1024];

            int len;

            while ((len = sisse.read(buf)) > 0) {

                välja.write(buf, 0, len);

            }

            sisse.close();

            välja.close();

        }

        catch (Exception e) {

            System.out.println("Erind: " + e);

        }

    }

}

Kaks märkust:

Ülesanne 1 (kontroll)

Muuta eelmist programmi nii, et juhul, kui sisendvoo allikaks on kataloog, väljastatakse vastav teade ja programm lõpetab töö. Juhul, kui tegemist on failiga, väljastada ekraanile faili suurus ja aeg, millal faili viimati muudeti.

Märkus: Abiks võiks olla meetod isDirectory() klassist File.


Java kasutab tekstilise info töötlemisel Unicode’i standardit. Sisseloetav ja väljastatav info peab läbima vastava teisenduse, millega tegelevad klassid Reader ja Writer. Näiteks klaviatuurilt klahvivajutuste lugemiseks ja Unicode’i kodeeringusse teisendamiseks võib kasutada klassi InputStreamReader:

InputStreamReader in = new InputStreamReader(System.in);

Siin on System.in Java standardsisendvoog, milleks vaikimisi on klaviatuur.

 

import java.io.*;

class Klaviatuurilt {

    public static void main(String[] args) {

        try {

            BufferedReader sisse = new BufferedReader (new InputStreamReader (System.in));

            System.out.print ("Anna tekst: ");

            String s = sisse.readLine();

            System.out.println ("Tippisid: " + s);

        }

        catch (IOException e) {

            System.out.println ("S/V viga: " + e);

        }

    }

}

Üks voog võib olla teise voo allikaks. Näiteks tekstifailist lugemiseks võib kasutada klassi BufferedReader, mille allikaks on märgivoog failist:

BufferedReader fr = new BufferedReader (new FileReader ("kiri.txt"));

Klaviatuurilt saab väärtusi sisestada vaid sõnena, vajalikule kujule teisendamiseks tuleb kasutada vastavaid meetodeid. Klaviatuurilt reakaupa lugemiseks sobib voog

BufferedReader fr = new BufferedReader (new InputStreamReader (System.in));

Siin teisendab InputStreamReader voo Unicode’i kodeeringusse ning seejärel BufferedReader puhverdab selle. Puhverdamist kasutatakse andmete edastuskiiruse suurendamiseks. Klasside ObjectInputStream ja ObjectOutputStream abil on voost võimalik lugeda ja sinna kirjutada ka objekte tervikuna.

 

Java standardteek sisaldab ka vahendeid failide kokku- ja lahtipakkimiseks.

Näide faili kokkupakkimisest zip-vormingusse:

  

import java.io.*;

import java.util.zip.*;

class Zipper { // failide pakkimine

    public static void zipi(String failiNimi, // parameetriteks pakitava faili viide,

                            String zipFailiNimi) { // pakitud faili viide

        byte[] buf = new byte[1024]; // andmevahetusbuffer

        try {

            // isend Zip-väljundi jaoks

            ZipOutputStream välja = new ZipOutputStream(new FileOutputStream(zipFailiNimi));

            // isend sisendfaili jaoks

            FileInputStream sisse = new FileInputStream(failiNimi);

            // ettevalmistus zip-faili väljastuseks

            välja.putNextEntry(new ZipEntry(failiNimi));

            int len;

            // sisendfailist lugemine ja zip-faili kirjutamine

            while ((len = sisse.read(buf)) > 0) {

                välja.write(buf, 0, len); // (andmed, nihe, pikkus)

            }

            välja.closeEntry();

            sisse.close();

            välja.close();

        }

        catch (IOException e) {}

    }

}

Ülesanne 2 - raskem

Lisada eelmisele klassile meetod zip-vormingus faili lahtipakkimiseks. Luua testklass demonstreerimaks failide kokku- ja lahtipakkimist.

Juhis: abiks võiks olla klass ZipInputStream ja selle klassi meetod getNextEntry().

Ülesanne 3 (kontroll)

Luua programm, mis etteantud tekstifaili ja sõne korral leiab sõne esinemiste arvu failis.

Juhis: selle ülesande lahendamiseks on mitu võimalust. Esiteks võite proovida lahendada seda ülesannet kasutades klasse File ja Scanner (nii nagu käis failist lugemine enne seda praktikumi, vt. praktikum 4). Teiseks võite proovida lahendada seda ülesannet kasutades klassi BufferedReader ja selle praktikumi näidet (BufferedReader fr = new BufferedReader(new FileReader("kiri.txt"));). Abiks võivad olla selle klassi meetodid ready() ja readLine().

Ülesanne 4 (kontroll)

Kirjutada programm, mis suunab klaviatuurisisendi tekstifaili.

Juhis: ka selle ülesande lahendamiseks on mitu võimalust. Esiteks, te saate seda lahendada nii nagu oli räägitud Praktikumis 4 (kasutades klasse File ja PrintWriter). Teiseks, aitavad teid klassid BufferedReader (ja selle meetod readLine()) ning FileOutputStream (ja selle meetod write(byte[] b, int off, int len)). Selleks, et String-ist teha byte-tüüpi järjendi võite kasutada meetodit getBytes().

Ülesanne 5

Kirjutada programm, mis klaviatuurilt sisestatud ja ekraanile väljastatavas tekstivoos asendab alamsõne "x" kõik esinemised alamsõnega "ks".

Ülesanne 6 (kontroll)

Koostada programm, millele antakse käsurealt (Eclipse'is Run-menüüst Run... --> Arguments (või Run Configurations... --> (x)=Arguments) ) ette "keelatud" sõnad. Klaviatuurilt sisestades jäetakse "keelatud sõnad" ekraanile väljastamata, teised väljatatakse.

Ülesanne 7

Loengus (11. loeng) vaadeldi ka algtüüpi andmete (DataOutputStream, DataInputStream) ja objektide (ObjectOutputStream, ObjectInputStream, Serializable) käsitlemist voogudega. Samuti otsejuurdepääsuga (RandomAccessFile) faile ning veebilelehekülge (URL, URLConnection) allikana.

Katsetada ka neid võimalusi vähemalt elementaarsel tasemel. Ühtki konkreetset ülesannet ei ole, aga tuleb valmis olla, et neid võimalusi tuleb rakendada 2. kontrolltöös.

Alternatiivne ülesanne

Mõne kontrollülesande (või keerulisemal juhul kõigi kontrollülesannete) asemel võib teha ka mingite oma eriala andmete töötlemisega seotud programmi, mis kasutab praktikumis kirjeldatud võimalusi.