15. Práce s datovými proudy Balík java.io obsahuje třídy, které slouží pro zpracování datových
výstupů a vstupů. Pro obvyklou práci se soubory zde můžeme najít třídy
File a RandomAccessFile. Většina tříd se však věnuje práci s datovými proudy. A to jak binárními
jejichž hlavní zastánci jsou třídy OutputStream a InputStream, tak
i znakovými jejichž hlavní třídy jsou Writer a Reader. Od hlavních
tříd je pak odvozena řada potomků, kteří se specializují na určité datové
proudy. V následujících podkapitolách můžete najít stručný popis hlavních tříd
s některými jejich metodami.
15.1. Třída File
Třída File umožňuje nezávisle na platformě definovat názvy souborů
a adresářů. Dále nabízí metody pro ověření existence, možnosti přístupu
(čtení/zápis), výpis souboru v adresáři, vytváření adresářů, přejmenování
adresářů/souborů a jejich mazání.
- public boolean exist() - test zda soubor/adresář existuje,
- public boolean isDirectory() - test na adresář,
- public boolean isFile() - test na soubor,
- public boolean canRead() - test na čtení souboru,
- public boolean canWrite() - test na zápis do souboru,
- public String getName() - vrací jméno souboru zbavené jmen
adresářů,
- public String getPath() - vrací jméno souboru s kompletní cestou,
- public String getParent() - vrací kompletní cestu k souboru,
- public long length() - vrací délku souboru,
- public boolean mkdir() - vytvoří adresář,
- public boolean mkdirs() - vytvoří adresář i s podadresáři,
- public boolean delete() - smaže soubor/adresář,
- public boolean renameTo(File cíl) - přejmenuje soubor,
- public String[] list() - zjistí všechny soubory/adresáře
odpovídající zadanému jménu při vytvoření objektu.
| Priklad 15.1. |
File soubor = new File("soubor.txt");
System.out.println("Délka souboru: " + soubor.length);
|
|
15.2. Třída RandomAccessFile
Tato třída umožňuje náhodný přístup k souboru a práci s ním. Otevření souboru
se provede při vytváření objektu konstruktorem. Ve třídě
RandomAccessFile jsou definovány dva veřejné konstruktory a to:
public RandomAccessFile(String soubor, String mód);
public RandomAccessFile(File soubor, String mód);
Parametr mód může být buď "r" pro otevření souboru jen pro čtení, nebo
"rw" pro otevření souboru pro zápis i čtení. Po otevření souboru je vždy
nastaveno ukazovátko na začátek souboru, a to v obou módech. Ani jeden mód
neruší obsah souboru.
- public native long getFilePointer() - vrací aktuální pozici v souboru,
- public native long length() - zjistí délku souboru,
- public native void seek(long poz) - nastaví pozici v souboru na poz,
- public native void close() - zavře soubor,
- public native int read() - načte jeden byte,
- public int read(byte b[]) - načte
b.length bytů,
- public final boolean readBoolean(), byte
readByte(),
char readChar(), ... - načte primitivní datový typ,
- public final String readLine() - načte řetězec v Unicode (viz příloha C.),
- public final String readUTF() - načte řetězec v UTF kódování (viz C.1.),
- public native void write(int b) - zapíše byte(!),
- public void write(byte b[]) - zapíše
b.length bytů,
- public final void writeBoolean(boolean v), void
writeByte(byte v), void writeChar(char v), ... - zapíše
primitivní datový typ,
- public final void writeBytes(String s) - zapíše řetězec jako sled bytů,
- public final void writeChars(String s) -
zapíše řetězec jako sled znaků,
- public final void writeUTF(String s) - zapíše
řetězec v kódování UTF,
| Priklad 15.2. |
import java.io.*;
public class KopirovaniSouboru
{
public static void main(String[] argv) throws IOException {
if (argv.length != 2) return;
File soubor1 = new File(argv[0]);
File soubor2 = new File(argv[1]);
if (!soubor1.isFile()) return;
if (soubor2.exists()) soubor2.delete();
RandomAccessFile zdroj = new RandomAccessFile(soubor1,"r");
RandomAccessFile cil = new RandomAccessFile(soubor2,"rw");
for (int n = 0; n < soubor1.length(); n++)
cil.writeByte(zdroj.readByte());
zdroj.close();
cil.close();
}
}
|
|
15.3. Třída InputStream
Abstraktní třída InputStream je rodičovskou třídou všech vstupních
bytových datových proudů. Definuje základní metody pro jejich zpracování.
- public InputStream() - veřejný konstruktor,
- public abstract int read() - načte byte,
- public int read(byte b[]) - načte
b.length bytů,
- public void close() - zavře vstupní datový proud,
- public long skip(long n) - přeskočí n bytů na
vstupu,
- public boolean markSupported() - vrací true
pokud vstupní datový proud podporuje "značkování",
- public synchronized void mark(int limit) - nastaví značku
v datovém proudu,
- public synchronized void reset() - vrací se zpět na značku.
Metodou mark() si lze označit aktuální pozici ve vstupním proudu a
metodou reset() se lze pak na tuto pozici vrátit. Pokud přesáhne
počet načtených bytů hodnotu, kterou udává parametr limit metody
mark, je značka zrušena. Tyto dvě metody lze však použít pouze tehdy,
vrátí-li metoda markSupported() hodnotu true.
Od abstraktní třídy InputStream jsou pak odvozeny například třídy:
FileInputStream - umožňuje přístup k souborům na nízké úrovni,
proto je používaná pro vlastní čtení metodami jiných tříd. Například třídou
DataInputStream.
FilterInputStream - poskytuje metody, které lze
použít pro filtrování dat ze vstupního proudu. Vlastní filtrování však
provádí její potomci. Mezi ně patří např. již zmiňovaná třída
DataInputStream.
PipedInputStream - slouží k vytvoření roury pro komunikaci
mezi vlákny (viz kap. 16.).
15.4. Třída OutputStream
OutputStream je abstraktní třída definující metody pro bytový výstupní
proud. Je rodičovskou třídou všech výstupních proudů.
- public OutputStream() - veřejný konstruktor,
- public abstract void write(int b) - zapíše byte(!),
- public void write(byte b[]) - zapíše
b.length bytů,
- public void flush() - vyprázdní výstupní vyrovnávací paměť,
- public void close() - zavře datový proud.
Mezi potomky třídy OutputStream patří např.
FilterOutputStream, FileOutputStream či PipedOutputStream.
Tyto třídy jsou obdobou tříd odvozených od třídy InputStream.
15.5. Třída Reader
Reader je abstraktní třída definující metody všech znakově orientovaných
vstupních datových proudů.
- public boolean ready() - zjistí, zda je k dispozici další znak,
- public int read() - načte jeden znak,
- public int read(char c[]) - načte
c.length znaků,
- public abstract void close() - zavře vstupní datový proud,
- public long skip(long n) - přeskočí (ignoruje) n znaků
na vstupu,
- public boolean markSupported() - vrací true
pokud vstupní datový proud podporuje "značkování",
- public void mark(int limit) - nastaví značku v datovém proudu,
- public void reset() - vrací se zpět na značku.
Funkce metod je obdobná jako u třídy InputStream.
15.6. Třída Writer
Writer je abstraktní třída definující metody všech znakově orientovaných
výstupních datových proudů.
- public void write(int c) - zapíše jeden znak,
- public void write(char c[]) - zapíše
c.length znaků,
- public void write(String s) - zapíše řetězec,
- void flush() - vyprázdní výstupní vyrovnávací paměť,
- public abstract void close() - zavře datový proud.
Funkce metod je obdobná jako u třídy OutputStream.
| Priklad 15.3. |
import java.io.*;
public class KopirovaniProudu
{
public static void main(String[] argv) throws IOException {
if(argv.length != 2) return;
File soubor1 = new File(argv[0]);
File soubor2 = new File(argv[1]);
if(!soubor1.isFile()) return;
if(soubor2.exists()) soubor2.delete();
FileInputStream zdroj = new FileInputStream(soubor1);
FileOutputStream cil = new FileOutputStream(soubor2);
for(int n = 0; n < soubor1.length(); n++)
cil.write(zdroj.read());
zdroj.close();
cil.close();
}
}
|
|
15.7. Standardní vstup a výstup
Standardní vstup a výstup je definován v třídě java.lang.System. V této
třídě je definován i standardní chybový výstup.Standardní vstup je označen identifikátorem in a je to instance třídy
InputStream. Oba výstupy jsou instancemi třídy PrintStream, která
je odvozena od třídy FilterOutputStream. Standardní výstup je označen
identifikátorem out, chybový výstup pak identifikátorem err. Třída PrintStream nabízí statické metody:
print( parametr )
println( parametr )
kde parametr může být některý z primitivních datových
typů boolean, char, double, float, int,
long a samozřejmě String.
| Priklad 15.4. |
System.out.print("Rozbijte wokna!");
System.out.println(1011);
|
|
Čtení z klávesnice je poněkud komplikovanější, jelikož abstraktní třída
InputStream nabízí jen metodu read() pro načtení jednoho bytu ze
vstupu.
| Priklad 15.5. |
|
Načtení řetězce o max. délce 30 znaků z klávesnice může vypadat takto:
byte pole[] = new byte[30]; // (1)
System.in.read(pole); // (2)
String text = new String(pole); // (3)
System.out.println("Zadal jsi: " + text); // (4)
Na řádce (1) je deklarováno bytové pole, do kterého je následně načten vstup
metodou read (2). Maximální délka vstupu je omezena hodnotou
pole.length. Vstup se ukončí klávesou ENTER. Pokud je vstup delší
je automaticky oříznut. Jelikož však vstup z klávesnice umožňuje vstup znaků
v ASCII kódu je nutné provést převod na Unicode. Na řádce (3) je k tomuto
účelu použít konstruktor třídy String, který převede bytové pole na
řetězec. Z tohoto je zřejmé, že tento převod lze použít pro znaky 0-127 ASCII
tabulky (viz příloha C.). Poslední řádka (4) pak načtený výsledek
zobrazí.
|
|
Základní datové typy je vhodné nejdříve načíst jako řetězec a pak provést
konverzi.
Jelikož Java je orientována na grafická rozhraní, je výhodnější používat pro
vstup a výstup knihovnu AWT (viz příloha A.).
|