Obsah
File
File
(2)File
(3)InputStream
Koncepce I/O proudů v Javě, skládání (obalování vlastnostmi)
Práce se soubory a adresáři, třída File
Binární proudy, abstraktní třídy InputStream, OutputStream
Znakové proudy, abstraktní třídy Reader, Writer
Serializace objektů
binární
(InputStream/OutputStream
)
koncipovány jako "stavebnice" - lze vkládat do sebe a tím přidávat vlastnosti, např.
is = new InputStream(...);
bis = new BufferedInputStream(is);
Téměř vše ze vstupních/výstupních tříd a rozhraní je v balíku java.io.
počínaje Java 1.4 se rozvíjí alternativní balík -
java.nio
(New I/O), zde se
ale budeme věnovat klasickým I/O z balíku
java.io
.
vše je opět v balíku java.io
základem je třída java.io.File
- nositel
jména souboru, jakási "brána" k fyzickým souborům na disku.
používá se jak pro soubory, tak adresáře, linky i soubory identifikované UNC jmény (\\počítač\adresář...)
opět plně platformově nezávislé
na odstínění odlišností jednotlivých systémů souborů lze použít vlastností (uvádíme jejich hodnoty pro JVM pod systémem MS Windows):
File.separatorChar \
- jako
char
File.separator \
- jako
String
File.pathSeparatorChar ;
- jako
char
File.pathSeparator ;
- jako
String
System.getProperty("user.dir")
- adresář
uživatele, pod jehož UID je proces JVM spuštěn
File
Vytvoření konstruktorem - máme několik možností:
vytvoří v aktuálním adresáři soubor s názvem filename
vytvoří v adresáři baseDir soubor s názvem filename
vytvoří v adresáři se jménem baseDirName soubor s názvem filename
vytvoří soubor se (souborovým - file:) URL url
File
(3)délka (velikost) souboru v bajtech
čas poslední modifikace v ms od začátku éry - podobně jako systémový čas vracený System.currentTimeMillis().
jen jméno souboru (tj. poslední část cesty)
celá cesta k souboru i se jménem
absolutní cesta k souboru i se jménem
adresář, v němž je soubor nebo adresář obsažen
Blíže viz dokumentace API třídy File.
Klíčem je opět třída File
- použitelná i pro
adresáře
Jak např. získat (filtrovaný) seznam souborů v adresáři?
pomocí metody File[] listFiles(FileFilter
ff)
nebo podobné
File[] listFiles(FilenameFilter fnf):
FileFilter je rozhraní s jedinou metodou boolean accept(File pathname), obdobně FilenameFilter, viz Popis API java.io.FilenameFilter
Vstupní jsou odvozeny od abstraktní třídy
InputStream
Výstupní jsou odvozeny od abstraktní třídy
OutputStream
Uvedené metody, kromě abstract byte read(), nemusejí být nutně v neabstraktní podtřídě překryty.
uzavře proud a uvolní příslušné zdroje (systémové "file handles" apod.)
poznačí si aktuální pozici (později se lze vrátit zpět pomocí reset())...
...ale jen když platí tohle
přečte bajt (0-255 pokud OK; jinak -1, když už není možné přečíst)
přečte pole bajtů
přečte pole bajtů se specifikací délky a pozice plnění pole b
vrátí se ke značce nastavené metodou mark(int)
přeskočí zadaný počte bajtů
InputStream
java.io.FilterInputStream - je bázová třída k odvozování všech vstupních proudů přidávajících vlastnost/schopnost filtrovat poskytnutý vstupní proud.
Příklady filtrů (ne všechny jsou v
java.io
!):
proud s vyrovnávací pamětí (je možno specifikovat její optimální velikost)
proud s kontrolním součtem (např. CRC32)
proud dešifrující data ze vstupu
má metody pro čtení hodnot primitivních typů, např.
float readFloat()
počítá současně i haš (digest) čtených dat, použitý algoritmus lze nastavit
dekomprimuje (např. GZIPem) zabalený vstupní proud (má ještě specializované podtřídy)
doplňuje informaci o tom, ze kterého řádku vstupu čteme (zavrhovaná - deprecated - třída)
přidává schopnost informovat o průběhu čtení z proudu
do proudu lze data vracet zpět
Příklad rekonstrukce objektů ze souborů
FileInputStream istream = new FileInputStream("t.tmp");
ObjectInputStream p = new ObjectInputStream(istream);
int i = p.readInt();
String today = (String)p.readObject();
Date date = (Date)p.readObject();
istream.close();
vstupní proud zvukových dat
proud dat čtených z pole bajtů
roura napojená na "protilehlý" PipedOutputStream
proud vzniklý spojením více podřízených proudů do jednoho virtuálního
proud na čtení serializovaných objektů
základem je abstraktní třída Reader
,
konkrétními implementacemi jsou:
nebudeme důkladně probírat všechny typy
jedná se o protějšky k vstupním proudům, názvy jsou
konstruovány analogicky (např. FileReader
->
FileWriter
)
místo generických metod read
mají
write(...)
poskytuje metody pro pohodlný zápis hodnot primitivních typů
a řetězců - příkladem jsou System.out
a
System.err
poskytuje metody pro pohodlný zápis hodnot primitivních typů a řetězců
Ze vstupního binárního proudu InputStream
(čili každého) je možné vytvořit znakový Reader
pomocí
// nejprve binární vstupní proud - toho kódování znaků nezajímá InputStream is = ... // znakový proud isr // použije pro dekódování standardní znakovou sadu Reader isr = new InputStreamReader(is); // sady jsou definovány v balíku
java.nio
Charset chrs = java.nio.Charset.forName("ISO-8859-2"); // znakový proud isr2 // použije pro dekódování jinou znakovou sadu Reader isr2 = new InputStreamReader(is, chrs);
Podporované názvy znakových sad naleznete na webu IANA Charsets.
Obdobně pro výstupní proudy - lze vytvořit Writer z OutputStream.
nebudeme podrobně studovat, zatím stačí vědět, že:
serializace objektů je postup, jak z objektu vytvořit sekvenci bajtů persistentně uložitelnou na paměťové médium (disk) a později restaurovatelnou do podoby výchozího javového objektu.
deserializace je právě zpětná rekonstrukce objektu
aby objekt bylo možno serializovat, musí
implementovat (prázdné) rozhraní
java.io.Serializable
proměnné objektu, které nemají být serializovány,
musí být označeny modifikátorem - klíčovým slovem -
transient
pokud požaduje "speciální chování" při de/serializaci, musí objekt definovat metody
metody:
Tutoriály k Java I/O: kapitola z Sun Java Tutorial
Demo programy na serializaci (z učebnice): Serializace objektů