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.).
|