Programovací jazyk Java

Podobné dokumenty
8. přednáška: Soubory a proudy

Soubor jako posloupnost bytů

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Úvod do programovacích jazyků (Java)

Z. Kotala, P. Toman: Java ( Obsah )

InputStream. FilterInputStream

Práce se soubory v Javě

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

6. PRÁCE S DATOVÝMI PROUDY

Semin aˇr Java V yjimky Radek Ko ˇc ı Fakulta informaˇcn ıch technologi ı VUT Unor 2008 Radek Koˇc ı Semin aˇr Java V yjimky 1/ 25

1. Téma 12 - Textové soubory a výjimky

Výjimky. v C# a Javě

Textové soubory. alg9 1

Úvod do programovacích jazyků (Java)

Předmluva k aktuálnímu vydání Úvod k prvnímu vydání z roku Typografické a syntaktické konvence... 20

Tento studijní blok má za cíl pokračovat v základních prvcích jazyka Java. Konkrétně bude věnována pozornost rozhraním a výjimkám.

Algoritmizace a programování

8 Třídy, objekty, metody, předávání argumentů metod

7. přednáška - třídy, objekty třídy objekty atributy tříd metody tříd

Proudy, Zpracovсnэ XML. Radek Koэ

Java - výjimky. private void vstup() throws IOException {... }

Přednáška 2. Systémy souborů OS UNIX. Nástroje pro práci se souborovým systémem. Úvod do Operačních Systémů Přednáška 2

29. Výjimky, jejich vznik, vyhození, odchyt a zpracování. (A7B36PVJ)

Java Výjimky Java, zimní semestr

7. Datové typy v Javě

typová konverze typová inference

Výčtový typ strana 67

Obsah přednášky 7. Základy programování (IZAPR) Přednáška 7. Parametry metod. Parametry, argumenty. Parametry metod.

Java a XML. 10/26/09 1/7 Java a XML

17. Projekt Trojúhelníky

Programování v Javě I. Leden 2008

Teoretické minimum z PJV

Počítačové laboratoře bez tajemství aneb naučme se učit algoritmizaci a programování s využitím robotů CZ.1.07/1.3.12/

Seminář Java II p.1/43

Programování v Javě I. Únor 2009

Ošetřování chyb v programech

Definice třídy. úplná definice. public veřejná třída abstract nesmí být vytvářeny instance final nelze vytvářet potomky

Regulární výrazy. Vzory

Class loader. každá třída (java.lang.class) obsahuje referenci na svůj class loader. Implementace class loaderu

KTE / ZPE Informační technologie

Seminář Java VI p.1/33

SOUBORY, VSTUPY A VÝSTUPY POKRAČOVÁNÍ

12. Dokumentace a distribuce aplikací. speciálních dokumentačních komentářích vpisovaných před

Úvod do programovacích jazyků (Java)

Příklad : String txt1 = new String( Ahoj vsichni! ); //vytvoří instanci třídy String a přiřadí ji vnitřní hodnotu Ahoj vsichni!

Dědičnost (inheritance)

Typický prvek kolekce pro české řazení

Úvod do programování - Java. Cvičení č.4

Výjimky. A0B36PR2-Programování 2 Fakulta elektrotechnická České vysoké učení technické

Výjimky. Tomáš Pitner, upravil Marek Šabo

Obsah přednášky 9. Skrývání informací. Skrývání informací. Zapouzdření. Skrývání informací. Základy programování (IZAPR, IZKPR) Přednáška 9

1. Programování proti rozhraní

Obsah. Úvod 11 Základy programování 11 Objektový přístup 11 Procvičování 11 Zvláštní odstavce 12 Zpětná vazba od čtenářů 12 Errata 13

UNIVERZITA PARDUBICE. Fakulta elektrotechniky a informatiky. Aplikace tříd souvisejících s přenosem dat mezi operační pamětí a diskem Marek Jelínek

Abstraktní datové typy: zásobník

Vstup/Výstup, Sokety. Duben 2012

Generické programování

Úvod do programování. Lekce 1

3. Třídy. Základní pojmy objektového programování. Třídy

Obsah přednášky. 12. Dokumentace zdrojového kódu Tvorba elektronické dokumentace UML. Co je diagram tříd. Ing. Ondřej Guth

Systém souborů (file system, FS)

Algoritmizace, základy programování, VY_32_INOVACE_PRG_ALGO_01

Programové konvence, dokumentace a ladění. Programování II 2. přednáška Alena Buchalcevová

20. Projekt Domácí mediotéka

7 Formátovaný výstup, třídy, objekty, pole, chyby v programech

KTE / ZPE Informační technologie

10. března 2015, Brno Připravil: David Procházka. Programovací jazyk C++

Připravil: David Procházka. Programovací jazyk C++

PŘETĚŽOVÁNÍ OPERÁTORŮ

Vytváření a použití knihoven tříd

Principy objektově orientovaného programování

Algoritmizace a programování

4. ZÁKLADNÍ POJMY Z OBJEKTOVĚ ORIENTOVANÉHO PROGRAMOVÁNÍ

Java - řazení objektů

Zápis programu v jazyce C#

Abstraktní třída a rozhraní

TŘÍDY POKRAČOVÁNÍ. Události pokračování. Příklad. public delegate void ZmenaSouradnicEventHandler (object sender, EventArgs e);

Programovací jazyk Java

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

PROMĚNNÉ, KONSTANTY A DATOVÉ TYPY TEORIE DATUM VYTVOŘENÍ: KLÍČOVÁ AKTIVITA: 02 PROGRAMOVÁNÍ 2. ROČNÍK (PRG2) HODINOVÁ DOTACE: 1

Java Řetězce Java, zimní semestr

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

VISUAL BASIC. Práce se soubory

Definice třídy. úplná definice. public veřejná třída abstract nesmí být vytvářeny instance final nelze vytvářet potomky

Enterprise Java (BI-EJA) Technologie programování v jazyku Java (X36TJV)

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

9. přednáška - třídy, objekty

O autorovi O odborném korektorovi Úvod 17 Vývoj jazyka Java Java SE 8 Struktura této knihy Předchozí zkušenosti s programováním nejsou potřebné

3 KTE / ZPE Informační technologie

Statické proměnné a metody. Tomáš Pitner, upravil Marek Šabo

Java Cvičení 01. CHARLES UNIVERSITY IN PRAGUE faculty of mathematics and physics

Práce se soubory. Základy programování 2 Tomáš Kühr

Datové struktury. alg12 1

Dynamicky vázané metody. Pozdní vazba, virtuální metody

IRAE 07/08 Přednáška č. 1

Remote Method Invocation RMI

Paměť počítače. alg2 1

Seznamy a iterátory. Kolekce obecně. Rozhraní kolekce. Procházení kolekcí

Projekty pro výuku programování v jazyce Java

Transkript:

1 z 7 14.1.2015 23:01 Programovací jazyk Java 4. přednáška Obsah Tvorba programátorské dokumentace Výjimky I/O operace Serializace a deserializace dat Práce se soubory Programátorská dokumentace pomocí JavaDoc Základním a standardním prostředkem je tzv. dokumentace API. Dokumentujeme především veřejné (public) a chráněné (protected) prvky (metody, proměnné). Ostatní dle potřeby. Dokumentaci píšeme přímo do zdrojového kódu programu ve speciálních dokumentačních komentářích vpisovaných před příslušné prvky (metody, proměnné). Typy komentářů řádkové od značky // do konce řádku, nepromítnou se do dokumentace API. utrata = pocetpiv 30; // komentář blokové začínají / a končí, mezitím komentář na libovolném počtu řádků. Nepromítnou se do dokumentace API. / Toto je muj prvni skvělý, jedinečný program, který nic nedělá. dokumentační od značky po značku, může být opět na libovolném počtu řádků. Každý další řádek může začínat mezerami či, hvězdička se v komentáři neprojeví. Promítnou se do dokumentace API. Dokumentační komentáře uvádíme především: Před hlavičkou třídy pak komentuje třídu jako celek. Před hlavičkou metody nebo proměnné pak komentuje příslušnou metodu nebo proměnnou. V dokumentačních komentářích lze používat HTML tagy! Generování dokumentace Dokumentace má standardně podobu HTML stránek (s rámy nebo bez). Dokumentace je generována nástrojem javadoc přímo ze zdrojového textu tříd. Na příkazovém řádku použijeme příkaz javadoc, v prostředí IDE najdeme příkaz k vytvoření dokumentace v menu. Spuštění: javadoc [options] [packagenames] [sourcefiles] [classnames] [@files] Vybrané volby (options): -help nebo -verbose nápověda -public, -protected, -package, -private specifikuje, které prvky mají být v dokumentaci zahrnuty (implicitně: -protected) -d destinationdirectory kam se má dokumentace uložit -doctitle title titul celé dokumentace Značky JavaDoc (vybrané) @author "autor 1" "autor 2" specifikuje autora(y) programu (jméno a příjmení uzavřít do uvozovek) @version verze označuje verzi API, např. "1.0" @deprecated informuje, že prvek je zavrhovaný (zastaralý) @exception výjimka popisuje informace o výjimce, kterou metoda propouští ( vyhazuje pomocí throws) @param parametr popis popisuje jeden parametr metody @see odkaz uvedeme odkaz, kam je také doporučeno nahlédnout (související věci) @link URL odkaz [popisek] uvedeme odkaz ve formě URL, kam je také doporučeno nahlédnout (související věci) Další značky: http://www.builder.cz/rubriky/java/javadoc-kompletni-pruvodce-tagy-155973cz Ukázka okomentované třídy package geometrie; Třída implementující geometrický útvar <strong>obdélník</strong> s atributy <i>vyska</i> a <i>sirka</i> a metodou pro výpočet obvodu. @author Petr Jedlička @version 1.00, 18. 10. 2012 public class Obdelnik { Výška obdélníku. private double vyska; Šířka obdélníku. private double sirka; Konstruktor obdélníku s parametry typu <tt>double</tt>. @param vyska Reálné číslo vyjadřující výšku obdélníku. @param sirka Reálné číslo vyjadřující šířku obdélníku. public Obdelnik(double vyska, double sirka) { this.vyska = vyska; this.sirka = sirka; Konstruktor obdélníku s parametry typu <tt>string</tt>. Ve svém těle volá konstruktor {@link #Obdelnik(double, double), který provede nastavení hodnot atributů {@link #vyska a {@link #sirka.

2 z 7 14.1.2015 23:01 @param vyska Číslo v podobě řetězce vyjadřující výšku obdélníku. @param sirka Číslo v podobě řetězce vyjadřující šířku obdélníku. @throws NumberFormatException Pokud řetězce zadané jako skutečné parametry při volání metody neobsahují reálná čísla. public Obdelnik(String vyska, String sirka) throws NumberFormatException { this(double.valueof(vyska), Double.valueOf(sirka)); Metoda, která počítá obvod trojúhelníku. @return Obvod trojúhelníku. public double getobvod() { return 2 (vyska + sirka); Nástroj JavaDoc poté vygeneruje dokumentaci v této podobě. Oficiální dokumentace k JavaDoc: http://www.oracle.com/technetwork/java/javase/documentation/index-137868.html Výjimky Mechanismus výjimek byl zaveden kvůli bezpečnosti programů. Nutí programátora předem reagovat na potenciální problémy (výjimečné stavy) v běhu programu (neotevřený soubor, málo paměti, ). Pokud v programu použijeme operace, které by mohly způsobit výjimku (např. metoda obyčejného čtení ze standardního vstupu System.in.read()), kompilátor nepřeloží program, dokud potenciální chybový stav (např. když na vstupu nic nebude) neošetříme. Možné druhy výjimek Java rozlišuje tři základní druhy výjimek: Error, RuntimeException a Exception. Programátora však nutí k ošetření pouze poslední uvedené výjimky (Exception), ošetření prvních dvou je dobrovolné. Všechny výjimky jsou potomky jedné třídy, třídy Throwable vyhoditelná. Třídy Error a Exception jsou potomky třídy Throwable, třída RuntimeException je potomkem třídy Exception. S třídou Throwable nepracujeme, protože se jedná o příliš obecnou chybu ( Nastala nějaká chyba. ) Na chyby třídy Error rovněž nereagujeme. To jsou chyby JVM (konkrétně interpretu Javy), na které ani reagovat neumíme (např. chyba OutOfMemoryError) Na výjimky třídy RuntimeException také nemusíme reagovat (i když můžeme). Tyto výjimky mohou nastat téměř kdekoliv a JVM je schopen je ošetřit. O výjimky třídy Exception se musíme v programu postarat. Tyto výjimky se vyskytují pouze v souvislosti s voláním určitých metod, u kterých je zvýšené nebezpečí výskytu chyby. Vždy je ale dobré vědět, jaké výjimky může volané metoda způsobit (najdeme v dokumentaci příslušné třídy). Třída Throwable Má mj. tyto konstruktory: Throwable() Throwable(String message) parametr message je zpráva, kterou po výskytu výjimky vrací metoda getmessage(). Throwable(String message, Throwable cause) parametr cause označuje příčinu výjimky (může být null). Throwable(Throwable cause) Má mj. tyto metody: String getmessage() vrací textový popis výjimky. StackTraceElement[] getstacktrace() metoda vrací pole záznamů o jednotlivých metodách na systémovém zásobníku v okamžiku, kdy došlo k výjimce. void printstacktrace() metoda vypisuje na std. výstup pořadí volání metod na systémovém zásobníku v okamžiku, kdy došlo k výjimce. Tento výstup může významně pomoci při odstraňování chyb v aplikaci. Způsoby ošetření výjimky Programátor má tři možnosti, jak reagovat na výjimku: 1. neošetřovat ji, pouze o ní podat informaci volající metodě, 2. výjimku zachytit a komplexně ošetřit, 3. výjimku částečně nebo komplexně ošetřit a současně předat informaci volající metodě. Předání výjimky volající metodě Při spuštění programu (na příkazové řádce příkazem java NazevTridy) se jako první hledá a spustí metoda main (má v Javě funkci hlavního programu). Z této metody se pak volají další metody a konstruktory. Každá metoda (s výjimkou metoda main u programů a metod init, start aj. u appletů) je tedy volána jinou metodou. Pomocí klíčového slova throws v hlavičce metody předáme případně vzniklou výjimku volající ( nadřazené ) metodě. Potom však musíme výjimku zase nějak řešit tam. Pokud výjimku nechceme řešit vůbec, vyhodíme ji i z metody main, tím se však vzdáváme možnosti řešit problém podle svého a necháváme řešení na JVM, který to bude řešit pravěpodobně ukončením programu. import java.io.ioexception; public class Vyjimka { private int pocetcihel; public int nacticisloint() throws IOException { byte[] pole = new byte[20]; System.in.read(pole); String nacteno = new String(pole).trim(); return Integer.valueOf(nacteno);

3 z 7 14.1.2015 23:01 public void nactivstupy() throws IOException { System.out.print("Zadej pocet cihel: "); pocetcihel = nacticisloint(); System.out.print("Zadej mnozstvi malty: "); Výjimka IOException je potomkem třídy Exception. IOException vzniká při vstupně výstupních operacích. Kompletní ošetření výjimky K této činnosti používáme jazykovou konstrukci try-catch(-finally) Do bloku try uzavřeme celý kód, ve kterém se může výjimka vyskytnout. Jedná se o tzv. chráněný blok. Blok catch, který za blokem try bezprostředně následuje, říká, na jakou výjimku se bude reagovat a jak. Těchto bloků může následovat i několik za sebou, každý může zachytávat jinou výjimku. V případě více výjimek (více bloků catch), jsou-li výjimky ve vztahu dědičnosti, je třeba v programu umístit dříve (výše) zachytávání speciálnější výjimky (podtřídy). Nepovinný koncový blok finally slouží k zápisu příkazů, které se mají provést, ať už výjimka nastane či nikoliv (např. vyprázdnění vyrovnávací paměti a uzavření souboru, do kterého jsme zapisovali). Syntaxe: // hlídaný blok catch(třídavýjimek1 referencenavýjimku1) { // ošetření výjimky 1 catch(třídavýjimek2 referencenavýjimku1) { // ošetření výjimky 2 finally { // zde uzavřený kód se provede vždy import java.io.ioexception; public class OsetreniVyjimky { private int pocetcihel; public int nacticisloint() { byte[] pole = new byte[20]; System.in.read(pole; String nacteno = new String(pole).trim(); return Integer.valueOf(nacteno); catch (IOException e) { System.out.println("Chyba pri cteni ze std. vstupu. Nastala vyjimka " + e.tostring()); e.printstacktrace(); return -1; catch (NumberFormatException e) { System.out.println("Chyba pri prevodu retezce na cislo. Nastala vyjimka " + e.tostring()); StackTraceElement[] zasobnik = e.getstacktrace(); for (int i = 0; i < zasobnik.length; i++) { System.out.print("Třída " + zasobnik[i].getclassname()); System.out.print(" uložená v souboru " + zasobnik[i].getfilename()); System.out.print(", metoda " + zasobnik[i].getmethodname()); System.out.println(", řádek " + zasobnik[i].getlinenumber() + "."); return -1; public void nactivstupy() { System.out.print("Zadej pocet cihel: "); pocetcihel = nacticisloint(); Při problému se čtením ze vstupu bude vytvořena a zachycena výjimka IOException a bude vypsáno: Chyba pri cteni ze std. vstupu. Nastala vyjimka java.io.ioexception java.io.ioexception -1 at OsetreniVyjimky.nactiCisloInt(OsetreniVyjimky.java:16) at OsetreniVyjimky.main(OsetreniVyjimky.java:48) Při problému s převodem řetězce na číslo (např. při zadání vstupu "abcd") bude vytvořena a zachycena výjimka NumberFormatException a bude vypsáno: Chyba pri prevodu retezce na cislo. Nastala vyjimka java.lang.numberformatexception: For input string: "abcd" Třída java.lang.numberformatexception uložená v souboru NumberFormatException.java, metoda forinputstring, řádek 65. Třída java.lang.integer uložená v souboru Integer.java, metoda parseint, řádek 492. Třída java.lang.integer uložená v souboru Integer.java, metoda valueof, řádek 582. Třída OsetreniVyjimky uložená v souboru OsetreniVyjimky.java, metoda nacticisloint, řádek 16. Třída OsetreniVyjimky uložená v souboru OsetreniVyjimky.java, metoda main, řádek 47. -1 Vyvolání výjimky Na výjimku je možné pohlížet jako na další datový typ Javy, který vrátí volaná metoda. Aby metoda mohla vrátit výjimku, musí metoda vytvořit odvozený objekt z třídy Exception a vyhodit takto vzniklou výjimku pomocí klíčového slova throw. Příklad vytvoření objektu výjimky IOException: void metoda() throws IOException { // tělo metody if (vyskytla_se_chyba) throw new IOException(); Příklad při zadání čísla 0 bude vyhozena výjimka: public int nacticisloint() { byte[] pole = new byte[20]; System.in.read(pole); String nacteno = new String(pole).trim(); int cisloint = Integer.valueOf(nacteno); if (cisloint <= 0) { throw new IllegalArgumentException("Počet cihel musí být kladný."); return cisloint; catch (IOException e) { System.out.println("Chyba pri cteni ze std. vstupu. Nastala vyjimka " + e.tostring()); e.printstacktrace(); return 0; catch (NumberFormatException e) { System.out.println("Chyba pri prevodu retezce na cislo. Nastala vyjimka " + e.tostring()); StackTraceElement[] zasobnik = e.getstacktrace(); for (int i = 0; i < zasobnik.length; i++) { System.out.print("Třída " + zasobnik[i].getclassname()); System.out.print(" uložená v souboru " + zasobnik[i].getfilename()); System.out.print(", metoda " + zasobnik[i].getmethodname()); System.out.println(", řádek " + zasobnik[i].getlinenumber() + "."); return 0; catch (IllegalArgumentException e) { System.out.println("Chybně zadaný vstup. Nastala vyjimka " + e.tostring()); e.printstacktrace(); return 0; Výpis při zadání vstupu 0: Zadej pocet cihel: 0

4 z 7 14.1.2015 23:01 Chybně zadaný vstup. Nastala vyjimka java.lang.illegalargumentexception: Počet cihel musí být kladný. java.lang.illegalargumentexception: Počet cihel musí být kladný. at pokusy.osetrenivyjimky.nacticisloint(osetrenivyjimky.java:27) at pokusy.osetrenivyjimky.nactivstupy(osetrenivyjimky.java:54) Vytvoření vlastní výjimky Děděním z nějaké knihovní třídy výjimky lze vytvořit vlastní výjimku a tu pak v případě potřeby vyvolat. class MojeIOVyjimka extends IOException { public MojeIOVyjimka(String zprava) { super(zprava); class MojeVyjimkaZaBehu extends RuntimeException { public MojeVyjimkaZaBehu(String zprava) { super(zprava); I/O operace Pro práci se soubory na disku, pro síťovou komunikaci, pro komunikaci mezi vlákny apod. potřebujeme mechanismus přenosu/přesunu dat. Základní způsob realizace vstupně-výstupních operací v Javě pomocí streamů ( proudů ). Stream si lze představit jako trubku, jejíž konec máme k dispozici a můžeme čerpat data z něho (tedy číst) nebo naopak do něho (tj. zapisovat). Stream vytvoříme jako objekt, tedy instanci určité třídy. Základní třídy pro práci se streamy obsahuje balík java.io. Známe dvě hlavní kategorie streamů: binární a textové. Textové jsou specializované na vstup/výstup textu, binární na obecný proud bajtů. Binární vstupní streamy jsou odvozeny od abstraktní třídy InputStream, výstupní od třídy OutputStream. Textové vstupní streamy jsou odvozeny od abstraktní třídy Reader, výstupní od třídy Writer. Životní cyklus streamu 4 etapy: 1. VYTVOŘENÍ (zavolání konstruktoru) může se vytvářet přímo tam, kde se používá, anebo ho může vytvořit nějaký jiný objekt a předat (např. jako parametr metody nebo naopak jako její návratovou hodnotu). 2. OTEVŘENÍ často už při vytváření, v každém případě však dříve, než se začne používat. Otevření znamená, že se alokují potřebné systémové prostředky a stream se připraví pro práci. 3. POUŽITÍ streamu. Se streamem se provádějí požadované operace, tzn. volají se jeho metody. 4. UZAVŘENÍ velmi důležité, často se na to zapomíná. Pokud neuzavřeme, vyčerpávají se systémové prostředky (file deskriptory apod.) a za druhé může mnoho dat zůstat nezapsaných (u výstupních streamů). Streamy proto zavíráme ihned, když s nimi přestáváme pracovat. Vybrané druhy streamů Přestože se se všemi streamy pracuje prakticky stejně, určité rozdíly jsou v jejich ůčelu a tím i způsobu přípravy. Používají se například tyto druhy streamů: Souborové streamy slouží ke čtení a zápisu souborů. Následující příklad ukazuje základní způsob čtení ze souborového streamu. Stream se otevře, v cyklu se z něho čte po bajtech (pozor i když se čtou bajty, hodnota je typu int). Pokud je přečtena hodnota 1, bylo dosaženo konce souboru). Všechny operace jsou uzavřeny do bloku try k zachycení výjimek. Streamy jsou instancemi tříd: FileInputStream pro čtení proudu bajtů ze souboru, FileOutputStream pro zápis proudu bajtů do souboru, FileReader pro čtení textu z textového souboru, FileWriter pro zápis textu do textového souboru. K zápisu na výstup slouží metoda instance write(), ke čtení ze vstupu metoda instance read(): Ukázka použití: FileInputStream fis = new FileInputStream("soubor.dat"); // stream se hned otevře int i = 0; while ((i = fis.read()) >= 0) { // čte se, dokud není konec souboru fis.close(); // zavření souboru catch (IOException e) { // zpracování výjimky Řetězcové streamy umožňují snadno číst z řetězce a zapisovat do něj streamovým způsobem. Stream pracuje nad objektem typu StringBuffer, ke kterému můžeme získat přímý přístup lze ale také ze streamu odvodit instanci třídy String. Streamy jsou instancemi tříd StringReader a StringWriter, používají se opět metody read() a write(). Ukázka: StringWriter sw = new StringWriter(); sw.write("abcd"); System.out.println(sw); Filtrové streamy skupina streamů, které slouží v podstatě k libovolnému zpracování procházejících dat. Typickým představitelem jsou bufferované streamy, které implementují buffer (vyrovnávací paměť). Například zápis do souboru, který by probíhal po samostatných bajtech, se provádí najednou až v okamžiku, kdy je jich připraveno víc. Používáme třídy BufferedInputStream, BufferedOutputStream, BufferedReader a BufferedWriter. Ukázka: BufferedReader br = new BufferedReader(new FileReader("soubor.txt")); String s = ""; while ((s = br.readline())!= null) { br.close(); catch (IOException e) { Při použití bufferovaných výstupních streamů není zaručeno, kdy se data z bufferu přesunou do navazujícího streamu. K zajištění zápisu dat z bufferu proto v případě potřeby voláme metodu flush(). PipedInputStream/PipedOutputStream a PipedReader/PipedWriter streamy. Tyto dva páry streamů představují tzv. rouru (pipe), což jsou vlastně vzájemně propojené streamy. Vezmeme jeden vstupní a jeden výstupní stream, propojíme je a s každým koncem pracujeme úplně stejně, jako by to byl normální vstupní, resp. výstupní stream. Nejčastějším použitím je komunikace mezi vlákny, kdy se v jednom vlákně vytvářejí nějaká data a současně se ve druhém tato data zpracovávají:

5 z 7 14.1.2015 23:01 Tyto streamy se vytvářejí tak, že vytvoříme jeden z nich a druhému ho předáme jako argument v konstruktoru. Jinou cestou je vytvořit je nezávisle a pak na některém z nich zavolat metodu connect(). Viz příklad: // první možnost PipedInputStream is = new PipedInputStream(); PipedOutputStream os = new PipedOutputStream(is); // druhá možnost PipedOutputStream os = new PipedOutputStream(); PipedInputStream is = new PipedInputStream(os); // třetí možnost PipedReader pr = new PipedReader(); PipedWriter pw = new PipedWriter(); pr.connect(pw); Serializace a deserializace dat Serializace je konverze obecných dat (nějakým způsobem uložených) na proud bajtů tak, aby je šlo následně snadno zrekonstruovat. Naopak deserializace je právě rekonstrukce proudu bajtů na data použitelná v programu. Java k těmto činnostem poskytuje výraznou podporu. Serializovat je nutno i hodnoty primitivních datových typů, např. int nebo double, k čemuž jsou připraveny třídy DataInputStream a DataOutputStream. Poskytují metody instance jako např. void writedouble(double v) a double readdouble(). Ukázka: int i = 165; float f = 0.35; DataOutputStream os = new DataOutputStream(new FileOutputStream("soubor.dat")); os.writeint(i); // bezpečné uložení hodnoty typu int os.writefloat(f); // bezpečné uložení hodnoty typu float os.close(); catch (IOException e) { Pro serializaci a deserializaci celých objektů máme třídy ObjectInputStream a ObjectOutputStream, které lze však použít i pro primitivní datové typy. Nelze ukládat všechny objekty. Nutnou podmínkou je, aby implementovaly rozhraní Serializable (pokud se pokusíme serializovat nevyhovující objekt, dočkáme se výjimky NotSerializableException). Protože se instance serializuje i se všemi odkazovanými objekty, musí být i tyto serializovatelné, anebo musí být jejich referenční proměnné označené modifikátorem transient (tedy že nebudou uloženy). Na rozdíl od primitivních typů, u objektů lze při deserializaci zjistit jejich typ (a nejen to, k úspěšné deserializaci musí být k dispozici příslušná třída jinak operace skončí výjimkou ClassNotFoundException. Metoda readobject() sice vrací referenci na typ Object, ale třídu si můžeme zjistit voláním getclass() na vrácené instanci nebo operátorem instanceof, a následně přetypovat podle potřeby. package geometrie; import java.io.; public class Obdelnik implements Serializable { private double vyska, sirka; private String jmeno; public Obdelnik(double vyska, double sirka, String jmeno) { this.vyska = vyska; this.sirka = sirka; this.jmeno = jmeno; public Obdelnik(String vyska, String sirka, String jmeno) throws NumberFormatException { this(double.valueof(vyska), Double.valueOf(sirka), jmeno); @Override public String tostring() { return "Obdelnik{" + "vyska=" + vyska + ", sirka=" + sirka + ", jmeno=" + jmeno + ''; public static void main(string[] args) { FileOutputStream fos = null; ObjectOutputStream oos = null; Obdelnik obd = new Obdelnik(5, 8, "Oskar"); fos = new FileOutputStream("c:\\temp\\obdelnik.tmp"); oos = new ObjectOutputStream(fos); oos.writeobject(obd); oos.writechar('r'); oos.close(); fos.close(); FileInputStream fis = new FileInputStream("c:\\temp\\obdelnik.tmp"); ObjectInputStream ois = new ObjectInputStream(fis); Object obj = ois.readobject(); if (obj instanceof Obdelnik) { Obdelnik obd2 = (Obdelnik) obj; System.out.println(obd2.toString()); char pismeno = ois.readchar(); System.out.println(pismeno); ois.close(); catch (ClassNotFoundException ex) { System.out.println(ex.toString()); catch (FileNotFoundException ex) { System.out.println(ex.toString()); catch (IOException ex) { System.out.println(ex.toString()); Práce se soubory Java je koncipována jako platformově nezávislá, takže se musí vypořádat s různými souborovými systémy. Zajímají nás především dvě nejrozšířenější skupiny souborových systémů: Systémy unixového typu je jich celá řada (UFS, Ext4, ReiserFS atd.), pro všechny z nich je typické, že celý systém tvoří jediný adresářový strom, jako oddělovač jednotlivých úrovní se používá běžné (dopředné) lomítko, rozlišují se velká a malá písmena, téměř všechny znaky ASCII jsou povolené pro použití v názvech souborů a pro ukládání názvů lze obecně používat různé kódové stránky. Systémy firmy Microsoft (FAT a NTFS) rozlišují se jednotlivá logická zařízení ( písmena disků ), oddělovačem je zpětné lomítko, velikost písmen se nerozlišuje, okruh platných znaků je poměrně malý (i když to některé systémové funkce řádně nekontrolují a lze tak na disk propašovat i soubory s neplatnými názvy, které pak lze těžko odstranit), kódování se liší podle jednotlivých systémů (NTFS používá Unicode, FAT potom staré kódové stránky, např. pro češtinu CP 852). Základní třídou pro práci se soubory je třída File z balíku java.io. Nepředstavuje přímo konkrétní soubor, nýbrž tzv. abstraktní cestu (tedy obecně jakoukoli cestu identifikující nějaký soubor). Může odkazovat na platný soubor, ale také nemusí. Je jakousi sofistikovanější náhradou zápisu cesty k souboru v podobě řetězce (objektu) typu String. Řada metod, které vyžadují jako svůj argument název souboru (např. konstruktor FileInputStream), jsou schopny přijmout jak odkaz na instanci třídy String, tak i

6 z 7 14.1.2015 23:01 File, což je přenositelnější a robustnější řešení, protože můžeme již předem zjistit o souboru daného názvu nějaké informace nebo provést se souborem potřebné operace. Objekt File může představovat jak soubory (běžné, ale i speciální, třeba soubory zařízení), tak adresáře. Cesta může být absolutní i relativní, může být dokonce i prázdná. Abstraktní cesta se vždy skládá z prefixu (např. označení kořenového adresáře; u relativních cest prefix samozřejmě chybí) a z posloupnosti názvů jednotlivých adresářových úrovní (samozřejmě včetně případného názvu souboru na konci) oddělených separátorem. Oddělovač názvů v cestě je ve třídě File určen hodnotou statické konstanty separatorchar (typu char), resp. separator (typu String). Na unixových systémech je oddělovačem samozřejmě dopředné lomítko, na microsoftích systémech lomítko obrácené. Operace s instancí třídy File Vytvoření instance třídy File: parametrem konstruktoru je buď String s relativní nebo absolutní cestou k souboru/adresáři (např. String path = "C:" + File.separator + "java" + File.separator + "projects" + File.separator + "cviceni9" + File.separator + "data.dat";), nebo instance třídy URI (např. URI u = new URI("http://old.mendelu.cz/~petrj/java/ppt/data.txt")). Práce s cestou k souboru. Objekt File je abstraktní cestou k souboru, se kterou můžeme pracovat a získávat různé její varianty. Lze získat celou cestu v různých podobách, části cesty a některé další verze. Metody: String getpath() vrátí abstraktní cestu v podobě, jak byla zadána při vytváření objektu (tedy absolutní zůstane absolutní atd.). Stejný efekt má i metoda String tostring(). String getabsolutepath() vrátí cestu převedenou do absolutního tvaru. Mechanismus případného převodu z relativní cesty na absolutní je platformově závislý, většinou se ale jako báze použije domovský adresář uživatele. String getcanonicalpath() vrací kanonický tvar cesty. V praxi to znamená, že se pokusí cestu maximálně vyhodnotit, zpracovat. Odstraní všechny označení stejného nebo nadřazeného adresáře (tečku a dvě tečky), zpracuje symbolické odkazy atd. Chování je silně platformově závislé a liší se podle toho, zda cesta (nebo její části) existuje či nikoli. String getname() získá z cesty pouhý název souboru (bez adresářové cesty). String getparent() vrací rodičovský adresář souboru. Vychází se pouze z cesty, soubor ani rodičovský adresář nemusí existovat. boolean isabsolute() zjistí, zda je cesta absolutní. int compareto(file pathname) lexikograficky porovná tuto abstraktní cestu s jinou (ani jedna nemusí existovat). Porovnávání je platformově závislé, podle systému se použije rozlišení malých/velkých písmen. Podobně pracuje metoda boolean equals(object obj), která pouze zjišťuje, zda jsou abstraktní cesty totožné. Adresářové informace. Předchozí metody se týkaly všech souborů bez rozdílu, tedy včetně adresářů. Pro adresáře samotné máme k dispozici speciální sadu metod, které využijeme pro přístup k souborům v těchto adresářích: String[] list() nejjednodušší varianta. Vrátí pole obsahující seznam všech souborů v daném adresáři položky tohoto pole budou textové řetězce s názvy souborů. Pořadí souborů není definováno, může být libovolné. File[] listfiles() dělá přesně totéž co list(), ale místo pole textových řetězců vrací pole objektů File, tedy abstraktních cest. String[] list(filenamefilter filter) modifikace metody list() s tím, že předem vybíráme jen některé soubory. Které to budou, to určí implementace rozhraní FilenameFilter (viz níže). File[] listfiles(filenamefilter f) modifikace metody listfiles() s tím, že opět předem vybíráme jen některé soubory. File[] listfiles(filefilter f) další modifikace, ale s jiným typem filtru. static File[] listroots() v souborových systémech unixovského typu je hierarchie přísně stromová, vždy máme jediný kořen. v jiných systémech to ale platit nemusí (a také neplatí), proto je třeba mít možnost dostat se ke všem dostupným kořenům a to zajišťuje právě tato statická metoda. Vrací pole všech kořenů adresářových stromů, které jsou v danou chvíli k dispozici. Při filtraci musíme implementovat rozhraní FilenameFilter nebo FileFilter. V obou případech musíme implementovat metodu boolean accept(). Pokud budeme implementaci potřebovat jen v jednom jediném případě, s výhodou využijeme možnosti vytvořit anonymní třídu přímo na daném místě. Viz příklad: File f = new File("/home/username/docs"); // vybereme adresář String[] list = f.list(new FilenameFilter() { boolean accept(file dir, String name) { return name.endswith(".pdf"); // jen názvy.pdf ); java.util.arrays.sort(list); // abecední seřazení for (int i = 0; i < list.length; i++) { System.out.println(list[i]); Manipulační operace: boolean renameto(file f2) metoda přejmenuje soubor podle zadání. Jako parametr se zadává jiná instance objektu File. Jelikož je původní instance File neměnná, i po úspěšném přejmenování souboru zůstane tak, jak je (bude obsahovat původní cestu k souboru). Naopak nové jméno souboru bude odpovídat zadané instanci f2, o čemž se můžeme přesvědčit tak, že zavoláme metodu boolean exists(). Chování je silně platformově závislé, nemůžeme spoléhat, že metoda bude dělat vždy to, co dělala na některé platformě. Návratovou hodnotu je třeba vždy testovat. boolean delete() pokusí se smazat soubor. Pokud to jde, smaže ho. Neprázdné adresáře mazat nelze, musíme je nejdříve vyprázdnit. void deleteonexit() zajímavá metoda, naplánuje smazání souboru při ukončování programu. Zafunguje pouze při regulérním ukončení programu, tedy ne při násilném (na Linuxu signálem SIGKILL) nebo při zavolání metody System.halt(). Metoda se používá pro automatické mazání dočasných souborů. Pozor! Naplánované smazání už nejde zrušit! boolean createnewfile() vytvoří nový prázdný soubor. static File createtempfile(string prefix, String suffix) vytvoří nový prázdný soubor v adresáři pro dočasné soubory. boolean mkdir(), boolean mkdirs() dvojice metod pro vytváření adresářů. Liší se pouze tím, že ta první vytvoří pouze ten jediný adresář, na který odkazuje instance File, kdežto ta druhá vytvoří, pokud je třeba, i všechny nadřazené adresáře. boolean setlastmodified(long time) změní časový údaj o poslední změně souboru. (Někdy se to může hodit.) boolean setreadonly() nastaví, že soubor bude pouze ke čtení. Operace pro zjištění informací: long gettotalspace() zjistí celkovou kapacitu (počet bajtů) diskového svazku, na kterém se nachází soubor. long getusablespace() zjistí volnou kapacitu (počet bajtů) diskového svazku, na kterém se nachází soubor. long length() zjistí velikost souboru (počet bajtů). long lastmodified() zjistí datum a čas poslední úpravy souboru. Hierarchie tříd datových proudů a textových proudů

7 z 7 14.1.2015 23:01 T h e E n d