Programovßnφ v jazyce Java
David ètrupl
Minul² dφl naÜeho serißlu jsme skonΦili popisem t°φd pro prßci se souborov²m systΘmem, konkrΘtn∞ t°φdou File.
Druhou t°φdou pro prßci se soubory je t°φda RandomAccessFile. Tato t°φda umo₧≥uje manipulaci se souborem, kterß neprobφhß sekvenΦn∞ (jako v p°φpad∞ pou₧itφ proud∙). Objekt t°φdy RandomAccessFile vytvo°φme podobn∞ jako v p°edchozφch p°φkladech ze jmΘna souboru. Jako druh² argument uvedeme zp∙sob otev°enφ souboru -- bu∩ hodnotu "r" p°i otev°enφ pouze pro Φtenφ nebo hodnotu "rw" pro Φtenφ i zßpis:
RandomAccessFile raf = new RandomAccessFile("mujSoubor.txt", "rw");
Po ·sp∞ÜnΘm otev°enφ se po souboru m∙₧eme pohybovat pomocφ metod:
- public void seek(long pozice),
- public int skipBytes(int n).
Krom∞ t∞chto metod m∙₧eme pou₧φt metody pro Φtenφ a zßpis, kterΘ jsou stejnΘ jako ve t°φdßch DataInputStream a DataOutputStream, nap°. readInt, writeInt apod.
Prßce se sφtφ
Knihovnu pro prßci se sφtφ najdeme v balφku java.net. Nejprve se podφvejme na t°φdy, kterΘ slou₧φ k reprezentaci adres na Internetu -- URL a InetAddress.
T°φda InetAddress reprezentuje IP adresu poΦφtaΦe. Objekty t°φdy InetAddress nevytvß°φme pomocφ volßnφ new a konstruktor∙, ale pomocφ jednΘ z nßsledujφcφch metod:
- public static InetAddress[] getAllByName(String),
- public static InetAddress getByName(String),
- public static InetAddress getLocalHost().
VÜechny tyto metody mohou zp∙sobovat v²jimku UnknownHostException, kterou musφme oÜet°it, chceme-li je zavolat. Pokud se nßm poda°φ vytvo°it objekt t°φdy InetAddress, m∙₧eme se ptßt na IP adresu pomocφ metod:
- public String getHostAddress(),
- public byte[] getAddress().
URL a URLConnection
Zajφmav∞jÜφ t°φdou pracujφcφ s Internetem je t°φda URL. Objekty tΘto t°φdy reprezentujφ URL a m∙₧eme je vytvo°it pomocφ volßnφ n∞kolika druh∙ konstruktor∙. NejjednoduÜÜφ je zadat jako parametr textovou reprezentaci URL:
URL mojeURL = new URL("http://www.sun.com");
VÜechny konstruktory tΘto t°φdy mohou zp∙sobovat v²jimku MalformedURLException -- je proto nutnΘ p°i ji v₧dy p°i vytvß°enφ nov²ch objekt∙ tΘto t°φdy oÜet°it.
Mßme-li ·sp∞Ün∞ vytvo°en objekt t°φdy URL, m∙₧eme si p°eΦφst data reprezentovanß tφmto URL pomocφ otev°enφ vstupnφho proudu z tohoto URL:
InputStream is = mojeURL.openStream();
Po otev°enφ vstupnφho proudu m∙₧eme Φφst data stejn∞ jako z ka₧dΘho jinΘho vstupnφho proudu. Ukß₧eme si nynφ cel² p°φklad, kter² vypφÜe na standardnφ v²stup data ze zadanΘho URL:
import java.io.*;
import java.net.*;
public class VypisURL {
public static void main(String arg[]) {
try {
URL mojeURL = new URL(arg[0]);
InputStream is=mojeURL.openStream();
int i = 0;
while (i != -1) {
i = is.read();
if (i != -1)
System.out.write(i);
}
is.close();
} catch (MalformedURLException x) {
System.out.println("Spatne URL");
} catch (IOException x) {
System.out.println("Chyba pri cteni");
}
}
}
Po p°elo₧enφ tohoto p°φkladu jej spustφme s parametrem zadßvajφcφm URL, jeho₧ obsah chceme vypsat (takΘ je dobrΘ pou₧φt program more, aby nßm v²sledek "neujel"):
java VypisURL http://www.idg.cz | more
Pokud chceme i n∞co zapisovat na danΘ URL, m∙₧eme vytvo°it objekt t°φdy URLConnection pomocφ volßnφ metody URL:
public URLConnection openConnection() throws IOException
Objekt typu URLConnection reprezentuje spojenφ ob∞ma sm∞ry, tj. m∙₧eme pou₧φt jeho metody:
- public InputStream getInputStream() throws IOException,
- public OutputStream getOutputStream() throws IOException.
V²stupnφ proud m∙₧eme pou₧φt nap°. k zapsßnφ HTTP hlaviΦky pro nßÜ dotaz.
Socket a ServerSocket
Druhou mo₧nostφ, jak pracovat se vzdßlen²m poΦφtaΦem, je pou₧itφ t°φdy Socket. Objekt tΘto t°φdy reprezentuje jeden konec TCP spojenφ na vzdßlen² poΦφtaΦ. Pokud se nßm poda°φ vytvo°it Socket, m∙₧eme op∞t dostat vstupnφ a v²stupnφ proud spojenφ na vzdßlen² poΦφtaΦ. Ukß₧eme si to na p°φkladu, kter² op∞t otev°e komunikaci se vzdßlen²m poΦφtaΦem:
Socket s = new Socket("www.idg.cz", 80);
InputStream is=s.getInputStream();
OutputStream os=s.getOutputStream();
Pomocφ tohoto volßnφ jsme op∞t zφskali dva vstupnφ proudy -- jeden pro zßpis a jeden pro Φtenφ.
Na zßv∞r povφdßnφ o sφtφch si ukß₧eme, jak jednoduchΘ je v Jav∞ napsat server, kter² poslouchß na n∞jakΘm portu. K tomuto ·Φelu pou₧ijeme t°φdu ServerSocket. ServerSocket umo₧≥uje velice jednoduchΘ vytvo°enφ serveru -- staΦφ si vybrat port a napsat nßsledujφcφ:
import java.io.*;
import java.net.*;
public class STest {
public static void main(String arg[]) {
try {
ServerSocket ss = new ServerSocket(5555, 5);
while (true) {
Socket s = ss.accept();
OutputStream os = s.getOutputStream();
PrintStream ps = new PrintStream(os);
ps.println("Vitam vas na serveru.");
ps.close();
}
} catch (IOException x) {
System.out.println("Chyba pri io.");
}
}
}
V konstruktoru pro ServerSocket jsme vybrali port 5555, druh² parametr znamenß, kolik spojenφ jsme ochotni nechat Φekat ve front∞. Pokud se nßm poda°ilo tento p°φklad p°elo₧it, m∙₧eme vyzkouÜet jak funguje nap°. pomocφ Telnetu. Po spuÜt∞nφ naÜeho programu spustφme jeÜt∞ Telnet a p°ipojφme se na localhost na port 5555. Pokud vÜe funguje, vypφÜe se nßm zadan² nßpis a spojenφ se ukonΦφ. Vzhledem k tomu, ₧e v programu je nekoneΦnß smyΦka, musφme jej ukonΦit pomocφ klßves CTRL-C.
Jak jsme vid∞li, je prßce se sφtφ v Jav∞ pom∞rn∞ jednoduchß -- na vytvo°enφ jednoduchΘho klienta i serveru nßm staΦφ n∞kolik °ßdek.
VφcevlßknovΘ aplikace (Multithreading)
V²znam pojmu vlßkno je podobn² starÜφmu pojmu proces. Mezi pojmy vlßkno a proces je n∞kolik drobn²ch rozdφl∙, kter²mi se zde nebudeme zab²vat. P°i b∞hu vφcevlßknovΘho programu, podobn∞ jako p°i vytvß°enφ vφce proces∙, dochßzφ k b∞hu n∞kolika Φßstφ programu souΦasn∞.
Podpora vφcevlßknov²ch (multithreaded) aplikacφ je obsa₧ena v balφku java.lang. Nejd∙le₧it∞jÜφ t°φdou pro prßci s vlßkny je t°φda Thread. Ukß₧eme si, jak vytvo°it novΘ vlßkno a jak toto vlßkno spustφme. Pro vytvo°enφ vlßkna mßme dv∞ mo₧nosti: vytvo°it potomka t°φdy Thread nebo implementovat rozhranφ Runnable. Vytvo°enφ potomka t°φdy Thread ukazuje nßsledujφcφ p°φklad:
class MojeVlakno extends Thread {
public void run() {
for (int i=0; i<1000; i++) {
// vypocet
}
}
}
public class TestVlaken {
public static void main(String args[]) {
MojeVlakno mv1 = new MojeVlakno();
mv1.start();
// pokracovani mainu
}
}
Vytvo°ili jsme potomka t°φdy Thread, kter² p°episuje jedinou metodu -- metodu run. Tato metoda je zavolßna, kdy₧ je novΘ vlßkno spuÜt∞no. SpuÜt∞nφ zajistφme zavolßnφm metody start. Cel² postup vytvo°enφ vlßkna je ilustrovßn v metod∞ main t°φdy TestVlaken: nejprve vytvo°φme objekt t°φdy MojeVlakno a ke spuÜt∞nφ pou₧ijeme metodu start.
Druh² Φasto pou₧φvan² zp∙sob vytvß°enφ vlßken je pou₧itφ rozhranφ Runnable. Jeho pou₧itφ nßs zbavuje nutnosti vytvß°et potomka t°φdy Thread. Ukß₧eme si pou₧itφ rozhranφ Runnable na p°φkladu appletu, kter² ve svΘ metod∞ start vytvo°φ novΘ vlßkno pro v²poΦet:
public class VlAplet extends java.applet.Applet implements Runnable {
public void run() {
for (int i=0; i<1000; i++) {
// vypocet
}
}
public void start() {
Thread mv1 = new Thread(this);
mv1.start();
}
}
Implementovat rozhranφ Runnable znamenß p°ipsat do svΘ t°φdy metodu run. Pokud to ud∞lßme, m∙₧eme v konstruktoru t°φdy Thread pou₧φt naÜi vlastnφ t°φdu, jako dodavatele metody run. Vytvo°enφ novΘho vlßkna pomocφ konstruktoru s parametrem znamenß, ₧e v okam₧iku spuÜt∞nφ tohoto vlßkna se spustφ metoda run objektu, kter² jsme zadali jako parametr. V naÜem p°φkladu je pou₧ito odkazu na nßÜ applet pomocφ klφΦovΘho slova this.
P°i psanφ vφcevlßknov²ch aplikacφ je n∞kdy t°eba pou₧φt synchronizaci jednotliv²ch vlßken. K tomuto ·Φelu obsahuje jazyk Java klφΦovΘ slovo synchronized. Pou₧itφ tohoto klφΦovΘho slova a n∞kolika synchronizaΦnφch metod obsa₧en²ch ve t°φd∞ Object vÜak nechßme na n∞jakou podrobn∞jÜφ publikaci, ne₧ je tento serißl.
DalÜφ mo₧nosti program∙ v Jav∞
Balφk standardnφch knihoven dodßvan²ch jako souΦßst JDK obsahuje jeÜt∞ n∞kolik zajφmav²ch Φßstφ, kterΘ jsou d∙le₧itΘ pro psanφ rozsßhlejÜφch aplikacφ v Jav∞. Tyto knihovny zde nebudeme podrobn∞ rozebφrat, pouze se seznßmφme s tφm co obsahujφ. Podrobn∞jÜφ v²klad je nad rßmec tohoto serißlu. Zßjemce odkazuji na dokumentaci k JDK a na dalÜφ publikace o Jav∞.
Knihovny, jejich₧ valnß Φßst je novß ve verzi JDK 1.1, jsou obsa₧eny v nßsledujφcφch balφcφch:
-java.beans -- Rozhranφ JavaBeans definuje formßt tzv. komponent, kterΘ mohou b²t pou₧ity v integrovan²ch v²vojov²ch prost°edφch jako stavebnφ kameny aplikace. Vyu₧itφ JavaBeans je d∙le₧itΘ p°i vizußlnφm navrhovßnφ aplikacφ.
-java.math -- Tato knihovna obsahuje objekty realizujφcφ matematickΘ v²poΦty v libovolnΘ p°esnosti.
-java.rmi -- rmi je zkratka slov Remote Method Invocation. Tento pom∞rn∞ rozsßhl² balφk umo₧≥uje psanφ distribuovan²ch aplikacφ pomocφ vzdßlenΘho vyvolßvßnφ metod.
-java.security -- Definuje rozhranφ pro bezpeΦnost a Üifrovßnφ.
-java.sql -- Jde o balφk obsahujφcφ rozhranφ JDBC (Java DataBase Connectivity). Slou₧φ pro p°ipojenφ Java aplikacφ k SQL server∙m.