Java programozási nyelv 10. rész Input/output kezelés Nyugat-Magyarországi Egyetem Faipari Mérnöki Kar Informatikai Intézet Soós Sándor 2005. szeptember A Java programozási nyelv Soós Sándor 1/28
Tartalomjegyzék Input/output eszközök a Java-ban Csatornák a Java-ban Csatornaosztályok a java.io csomagban Bájt- és karaktercsatornák Szabványos be- és kimenet, hibacsatorna Csatornák alapfunkciói Adatforrások és adatnyelők Hasznos szűrőosztályok Egyéb fájlkezelő eszközök a Java-ban A Java programozási nyelv Soós Sándor 2/28
Input/output eszközök a Java-ban A Java csatornák (stream-ek) segítségével valósítja meg az I/O műveletek nagy részét. Egy csatorna adatok sorozata, egyik végén befelé a másik végén kifelé "folynak" az adatok. A Java program szempontjából vannak bemeneti és kimeneti csatornák. A csatornák mellett a Java rendelkezik eszközökkel a közvetlen elérésű fájlok és a helyi fájlrendszerek kezeléséhez is. A Java programozási nyelv Soós Sándor 3/28
Bemeneti csatornák Csak a csatorna elejéről tudunk adatokat elolvasni és levenni Tartozik hozzá egy adatforrás, ami adatokkal táplálja a csatornát. Az adatforrás sok minden lehet: billentyűzet fájl egy String egy program egy hálózati végpont egy másik csatorna kimenete stb. A Java programozási nyelv Soós Sándor 4/28
Kimeneti csatornák Csak a csatorna végére tudunk adatokat írni Tartozik hozzá egy adatnyelő, ahova a kiírt adatok mennek Az adatnyelő sok minden lehet: képernyő fájl egy String egy program egy hálózati végpont egy másik csatorna bemenete stb. A Java programozási nyelv Soós Sándor 5/28
Csatornák a Java-ban Ahogyan minden mást, a csatornákat is osztályokkal valósítjuk meg a Java-ban. Minden csatorna típusnak egy-egy osztály felel meg. A csatornákat megvalósító osztályok a java.io csomagban találhatók. A Java programozási nyelv Soós Sándor 6/28
Csatornaosztályok csoportosítása A csatorna iránya alapján vannak: bemeneti osztályok kimeneti kimeneti A csatornán folyó adatok típusa szerint vannak: bájtcsatorna-osztályok karaktercsatorna-osztályok Feladatuk szerint vannak forrás osztályok nyelő osztályok a csatornát módosító osztályok A Java programozási nyelv Soós Sándor 7/28
Az alap csatornaosztályok Típus\Irány Bemeneti Kimeneti Bájt InputStream OutputStream Karakter Reader Writer Az ezekből származó osztályok így végződnek. A név végéből tudhatjuk, hogy milyen típusú osztályról van szó. Például: FileInputStream, FileOutputStream, FileReader, FileWriter A Java programozási nyelv Soós Sándor 8/28
Csatornaosztályok a java.io csomagban (Az ábra JPEG formátumban megtalálható a példák között) A Java programozási nyelv Soós Sándor 9/28
Bájt- és karaktercsatornák A két típus a csatorna által kezelt legkisebb adategység típusában különbözik: bájt: 8 bit char: 16 bit, (Unicode) A két osztálycsalád nagyon sok szempontból hasonlít egymásra. Amit az egyik típusról megtanultunk, azt a másiknál is használhatjuk értelemszerű módosításokkal. Például: OutputStream: public void write( byte c[] ) throws IOException Writer: public void write( char c[] ) throws IOException A Java programozási nyelv Soós Sándor 10/28
Feladat szerinti csoportosítás Bemeneti csatornák, forrásosztályok: Pl. FileInputStream, FileReader Kimeneti csatornák, nyelőosztályok: Pl. FileOutputStream, FileWriter Szűrők: egy meglévő csatornát új képességekkel, tulajdonságokkal egészít ki. Például: BufferedInputStream, BufferedReader: az InputStream, illetve a Reader pufferelt beolvasást biztosító változata. A szűrőket mindig egy létező csatornaobjektum "fölé" hozzuk létre, a konstruktorának átadjuk a csatorna objektumot. A Java programozási nyelv Soós Sándor 11/28
Példa a szűrőkre PrintWriter: a hozzárendelt csatornát kiegészíti a különböző adattípusok szöveges kiírásának képességével. Konstruktorának meg kell adni egy kimeneti csatornát, ezt fogja kiegészíteni ezzel a képességgel. FileWriter fout = new FileWriter( "printwriter.txt" ); PrintWriter out = new PrintWriter( fout ); vagy PrintWriter out = new PrintWriter( new FileWriter( "printwriter.txt" ) ); A Java programozási nyelv Soós Sándor 12/28
Szabványos be- és kimenet, hibacsatorna System.in public static final InputStream in A standard inputhoz van rendelve a program elindulásakor System.out public static final PrintStream out A standard outputhoz van rendelve a program elindulásakor System.err public static final PrintStream err A standard hibakimenethez van rendelve a program elindulásakor Átirányíthatók az operációs rendszer szintjén. A Java programozási nyelv Soós Sándor 13/28
Csatornák alapfunkciói Ezeket a funkciókat a négy alaposztály definiálja: InputStream, OutputStream, Reader, Writer A többi osztály ezektől örökli őket. Az alapfunkciók: Csatorna megnyitása, lezárása Kiíró műveletek Olvasó műveletek Könyvjelző-mechanizmus Egyéb műveletek A Java programozási nyelv Soós Sándor 14/28
Csatornák megnyitása és lezárása A Java I/O osztályoknak nincsen külön megnyitó metódusa, a konstruktor hozza létre és rögtön meg is nyitja a csatornát. A csatorna lezárására a close() metódus szolgál. Kimeneti csatornák esetén a close() végrehajtja a flush() metódust is, azaz lemezre menti a pufferek tartalmát. Ha lezárt csatornára próbálunk meghívni valamilyen író/olvasó műveletet, akkor IOException kivételt kapunk. Például: FileWriter fout = new FileWriter("filenev.txt");... // itt lehet használni a csatornát fout.close(); A Java programozási nyelv Soós Sándor 15/28
Kiíró műveletek Mind a bájt, mind a karakter típusú kimeneti csatornák rendelkeznek a következő 3 kiíró metódussal: public void write( int i ) throws IOException public void write( byte t[] ) throws IOException public void write( byte t[], int off, int len ) throws IOException karaktercsatornák esetén byte helyett char értendő Az első write metódus a paraméter 1 vagy 2 legalsó bájtját írja ki. A karaktercsatornák rendelkeznek a következő 2 metódussal is: public void write( String s ) throws IOException public void write( String s, int off, int len ) throws IOException A Java programozási nyelv Soós Sándor 16/28
Olvasó műveletek Mind a bájt, mind a karakter típusú kimeneti csatornák rendelkeznek a következő 3 beolvasó metódussal: public int read() throws IOException public int read( byte t[] ) throws IOException public int read( byte t[], int off, int len ) throws IOException karaktercsatornák esetén byte helyett char értendő Az első read metódus 1 vagy 2 bájtot olvas be, majd int-té alakítva adja vissza. A másik kettő annyi adatot olvas, amennyi a megadott tömbben, vagy résztömbben elfér. Visszaadja a beolvasott adategységek (byte, vagy char) számát, vagy -1-et, ha nem volt olvasható adat. A Java programozási nyelv Soós Sándor 17/28
Példa: fájlok másolása Az eddig látott eszközökkel már le tudunk másolni fájlokat. A write() és a read() metódusokkal bájtról-bájtra másolhatunk: masolo.java A tömbökkel dolgozó read és write metódusokkal viszont pufferelt másolást végezhetünk: masolob.java Mi a szerepe a pufferelésnek? Mekkora legyen a pufferméret? Miért? A Java programozási nyelv Soós Sándor 18/28
Hogyan kezeljük a csatorna végét? A beolvasó műveletek megkülönböztetik az üres és a véget ért csatornákat. Üres egy csatorna, ha pillanatnyilag nem tartalmaz adatot. Ilyenkor a beolvasó műveletek addig várakoznak, amíg nem érkezik adat. Véget ért egy csatorna, ha a csatorna végét jelző jel érkezik meg rajta (fájl vége, UNIX-ban Ctrl- D, DOS-ban Ctrl-Z billentyű) Nézzük meg a Billentyu.java fájlt! A Java programozási nyelv Soós Sándor 19/28
Könyvjelző-mechanizmus Ezzel a témakörrel nem foglalkozunk részletesen. Akit érdekel a dolog nézzen utána a mark, marksupported és a reset metódusoknak! A Java programozási nyelv Soós Sándor 20/28
Egyéb műveletek public long skip( long n ) throws IOException n darab adategységet átlép beolvasás nélkül visszaadja a ténylegesen átugrott adategységek számát public boolean ready( ) throws IOException karakter csatornáknál megadja, hogy van-e beolvasható adat. ha igaz, akkor az egy karaktert beolvasó read() nem blokkolódik public int available( ) throws IOException bájt csatornák esetén megadja, hogy minimálisan hány bájt áll rendelkezésre a csatornán. A Java programozási nyelv Soós Sándor 21/28
Adatforrások és adatnyelők Egy csatorna létrehozásakor meg kell adnunk, hogy milyen fizikai adattároló kapcsolódjon hozzá. A csatorna típusa meghatározza, hogy mi jöhet szóba, a konkrétumokat pedig a konstruktornak adjuk át. Például a FileWriter egy fájlhoz csatlakozó kimeneti karaktercsatorna. Létrehozása: new FileWriter( "filenev.txt" ); A következő oldalakon sorra vesszük a leggyakoribb adatforrásokat és adatnyelőket. A Java programozási nyelv Soós Sándor 22/28
Fájlok Ha egy csatornához hozzá akarunk rendelni egy fájlrendszerbeli fájlt, akkor a FileInputStream, FileOutputStream, illetve FileReader vagy FileWriter osztályt kell használnunk. A konstruktornak át kell adnunk egy hivatkozást a fájlra Stringként, vagy egy File objektumként. Ügyeljünk az elérési út formátumára (rendszerfüggő)! InputStream fst = new FileInputStream( "file.txt") String elv = System.getProperty("file.separator"); Writer wf = new FileWriter(elv+"tmp"+elv+"file.txt"); Nézzük meg a fajlnev.java fájlt! A Java programozási nyelv Soós Sándor 23/28
Bájt- és karaktertömbök, Stringek Egy csatornát hozzákapcsolhatunk tömbökhöz, vagy Stringekhez. Ehhez a következő osztályokat használhatjuk: ByteArrayInputStream ByteArrayOutputStream CharArrayReader CharArrayWriter StringReader StringWriter Nézzük meg a sw.java fájlt! A Java programozási nyelv Soós Sándor 24/28
Bájtcsatorna feletti karaktercsatornák Az InputStreamReader és az OutputStreamWriter osztályok összekapcsolják a bájt és karakter csatornákat. Ezek olyan karaktercsatornák, amelyek bájtcsatornák felett vannak definiálva, 16 bites Unicode karaktereket írunk és olvasunk, de azok 8 bites bájtok formájában utaznak a csatornán. A konstruktornak megadhatjuk, hogy milyen szabvány szerint konvertáljon. Lásd Latin2.java! A Java programozási nyelv Soós Sándor 25/28
Bemeneti csatornák összefűzése A SequenceInputStream osztállyal összefűzhetünk több bemeneti csatornát. Nézzük meg a papsajt.java fájl-t! A Java programozási nyelv Soós Sándor 26/28
Hasznos szűrőosztályok DataOutputStream, DataInputStream: különböző adattípusok kiírásával egészíti az eredeti csatornát Nézzük meg a vacsora.java fájlt! PrintStream, PrintWriter: különböző adattípusok szöveges kiírásával egészíti az eredeti csatornát Nézzük meg a okos.java fájlt! Csatornák bufferelése BufferedInputStream, BufferedReader, BufferedOutputStream, BufferedWriter Nézzük meg a sum.java fájlt! A Java programozási nyelv Soós Sándor 27/28
Egyéb fájlkezelő eszközök a Java-ban Nem stream alapú fájlkezelő osztályok: RandomAccessFile osztály: közvetlen elérésű fájlok Nézzük meg a raf.java fájlt! A helyi fájlrendszer fájljainak kezelése: File osztály Nézzük meg a fajlok.java fájlt! A Java programozási nyelv Soós Sándor 28/28