NIO. Aplikační programování v Javě (BI-APJ) - 12 Ing. Jiří Daněček Katedra softwarového inženýrství Fakulta informačních technologií ČVUT Praha



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

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

Technologie JavaBeans

Úvod do programovacích jazyků (Java)

Soubor jako posloupnost bytů

Se vznikem internetu se můžeme na síťovou komunikaci v Javě (komunikace mezi více JVM) dívat dvěma pohledy-způsoby:

ANT. Aplikační programování v Javě (BI-APJ) - 1 Ing. Jiří Daněček Katedra softwarového inženýrství Fakulta informačních technologií ČVUT Praha

Teoretické minimum z PJV

Algoritmizace a programování

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

Java Výjimky Java, zimní semestr

Vláknové programování část V

Typický prvek kolekce pro české řazení

6. PRÁCE S DATOVÝMI PROUDY

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

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

RMI Remote Method Invocation

Fronta (Queue) Úvod do programování. Fronta implementace. Fronta implementace pomocí pole 1/4. Fronta implementace pomocí pole 3/4

Práce se soubory v Javě

Příklad aplikace Klient/Server s Boss/Worker modelem (informativní)

Programování v Javě I. Leden 2008

KTE / ZPE Informační technologie

Výjimky. v C# a Javě

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

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

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

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

Čipové karty Lekařská informatika

JSR tutorial 2 Transformace v JSR-184

5 Rekurze a zásobník. Rekurzivní volání metody

Java Řetězce Java, zimní semestr

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

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

Základy jazyka C# Obsah přednášky. Architektura.NET Historie Vlastnosti jazyka C# Datové typy Příkazy Prostory jmen Třídy, rozhraní

OSGi. Aplikační programování v Javě (BI-APJ) - 6 Ing. Jiří Daněček Katedra softwarového inženýrství Fakulta informačních technologií ČVUT Praha

20. Projekt Domácí mediotéka

Iterator & for cyklus

George J. Klir. State University of New York (SUNY) Binghamton, New York 13902, USA

Úvod do programovacích jazyků (Java)

Pokud zadání nerozumíte nebo se vám zdá nejednoznačné, zeptejte se. Pište čitelně, nečitelná řešení nebudeme uznávat.

Principy objektově orientovaného programování

PREPROCESOR POKRAČOVÁNÍ

Úvod Jednoduchá komunikace Sockety Konec. Programování v C# Síťová komunikace. Petr Vaněček 1 / 33

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

Zápis programu v jazyce C#

Pokud zadání nerozumíte nebo se vám zdá nejednoznačné, zeptejte se. Pište čitelně, nečitelná řešení nebudeme uznávat.

Textové soubory. alg9 1

Distribuované systémy a výpočty

Univerzita Palackého v Olomouci Radek Janoštík (Univerzita Palackého v Olomouci) Základy programování 4 - C# 19.2.

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

Distribuované systémy a výpočty

InputStream. FilterInputStream

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

Ošetřování chyb v programech

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

Datové struktury. alg12 1

Pokud zadání nerozumíte nebo se vám zdá nejednoznačné, zeptejte se. Pište čitelně, nečitelná řešení nebudeme uznávat.

Proměnné a datové typy

public class Karel { private int position; public boolean issmiling; public int getposition() { return position;

typová konverze typová inference

Soketové připojení Klient InetAddress getbyname() UnknowHostException SecurityException Socket getinputstream() getoutputstream() IOException Server

JAVA V RMI Java, letní semestr

Stromy. Příklady. Rekurzivní datové struktury. Základní pojmy

RMI - Distribuované objekty v Javě

Java a Caché IV: Manipulace s objekty

IMPLEMENTACE INFORMAČNÍHO SYSTÉMU VIDIUM V JAZYCE JAVA

Java Enum Java, zimní semestr ,2017 1

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

Práce s textem. Třída Character. Třída Character. Třída Character. reprezentuje objekty zapouzdřující hodnotu typu char (boxing / unboxing)

Úvod do programovacích jazyků (Java)

Abstraktní datové typy: zásobník

Úvod do Javy, JDBC a multimediální databáze

PES lib (C + PASCAL) KNIHOVNY KOMUNIKAÈNÍCH FUNKCÍ 03/ PESlib KOMUNIKAČNÍ KNIHOVNY C, PASCAL 03/ stran 1

Datové struktury. Obsah přednášky: Definice pojmů. Abstraktní datové typy a jejich implementace. Algoritmizace (Y36ALG), Šumperk - 12.

Řídicí struktury. alg3 1

11. Dědičnost. Dědičnost strana 103

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

JAVA RMI Java, letní semestr 2018

SW_10. Dekorátor - Decorator Stav - State

public static void main(string[] args) { System.out.println(new Main().getClass().getAnnotation(Greet.class).text());

Tabulka symbolů. Vazba (binding) Vazba - příklad. Deklarace a definice. Miroslav Beneš Dušan Kolář

Část 1 Příklad GUI aplikace Simulátor/Plátno. GUI s plátnem Struktura aplikace Struktura simulátoru Struktura grafického rozhraní Praktické ukázky

Objektově orientované programování

X-komponenty 3.1. Uživatelská příručka. J. Kocman, V. Trojan

PB161 Programování v C++ Proudy pro standardní zařízení Souborové proudy Paměťové proudy Manipulátory

Regulární výrazy. Vzory

součet cvičení celkem. známka. Úloha č.: max. bodů: skut. bodů:

Vstupně - výstupní moduly

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

Webové služby a XML. Obsah přednášky. Co jsou to webové služby. Co jsou to webové služby. Webové služby a XML

Katedra měřicí a řídicí techniky, VŠB - Technická univerzita v Ostravě, tř. 17. listopadu, Ostrava-Poruba, Česká republika

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/

VISUAL BASIC. Práce se soubory

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

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

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

7. Dynamické datové struktury

Jini (pronounced GEE-nee) Cvičení 8 - DS 2006

Principy operačních systémů. Lekce 2: Správa paměti

LED_007.c Strana: 1/5 C:\Michal\AVR\Výukové programy\archiv\ Poslední změna: :01:48

Transkript:

NIO Aplikační programování v Javě (BI-APJ) - 12 Ing. Jiří Daněček Katedra softwarového inženýrství Fakulta informačních technologií ČVUT Praha Evropský sociální fond Praha & EU: Investujeme do vaší budoucnosti

Úvod Knihovna NIO (java.nio) byla zaveden do JDK od verze 1.4 jako nadstavba standardní knihovny java.io. Jejím hlavním účelem je zprostředkovat aplikacím přímý přístup k rychlým nativním I/O operacím, které poskytuje operační systém. Hlavní vlastnosti NIO: vysoká rychlost využití blokových přenosů neblokovaný vstup a výstup možnost využití DMA využití SSL

Abstraktní třída Buffer Buffer je konečná vyrovnávací paměť slotů na elementy primitivního typu. Buffer pracuje buď v režimu čtení nebo zápisu. Buffer má následující vlastnosti: capacity - fixní počet slotů, position - index první pozice, která se bude dále zpracovávat. V režimu čtení je to první element, který se bude číst, v režimu zápisu je to první volný slot. limit - index první pozice, která se naopak nebude zracovávat. V režimu čtení z bufferu je to první volný slot, v režimu zápisu je to capacity. Pro buffer platí invariant: 0 <= mark <= position <= limit <= capacity Pro každý primitivní typ je definována podtřída: ByteBuffer, IntBuffer,... atd.

Základní operace nad Buffer Do bufferu se v jednom okamžiku buď zapisuje nebo se z něj čte. public final Buffer flip() - překlopení bufferu z režimu zápis do režimu čtení: limit je nastaven na position position je nastavena na 0. public final Buffer clear() - vymazání bufferu. position je nastavena na 0, limit je nastaven na capacity. public final int remaining() - vrátí počet elementů mezi position a limit tj. buď počet zbývajících elementů v režimu čtení nebo počet zbývajících volných slotů v režimu zápisu.

Třída ByteBuffer Základní konkrétní buffer. Umožňuje: zápis a čtení jednotlivých bytů a dále polí bytů. zápis a čtení primitivních datových typů, vytváření pohledových bufferů. Metody pro vytvoření objektu ByteBuffer: static ByteBuffer allocatedirect(int capacity) - vytvoří tzv. přímý buffer. Pro přímý buffer JVM "make a best effort to perform native I/O operations directly upon it" - t.zn bez kopírovacích operací po každé nativní I/O operaci. Přímý buffer může existovat mimo oblast heapu! static ByteBuffer allocate(int capacity) - vytvoří nepřímý ByteBuffer o zadané kapacitě, který je zálohován bytovým polem.

Základní metody pro čtení a zápis Metody pro čtení z ByteBuffer. Pokud operaci nelze provést je hozena výjimka BufferUnderflowException: byte get() - relativní čtení. Vrátí byte a inkrementuje position, byte get(int index) - absolutní čtení z indexu, ByteBuffer get(byte[] dst) - relativní blokové čtení. Přesune byty z bufferu do dst. Metody pro zápis do ByteBuffer. Pokud operaci nelze provést je hozena výjimka BufferOverflowException: ByteBuffer put(byte b) - relativní zápis bytu, ByteBuffer put(int index, byte b) - absolutní zápis bytu, ByteBuffer put(byte[] src) - relativní zápis pole bytů.

Čtení a zápis jednoduchých typů ByteBuffer má metody pro čtení a zápis jednotlivých elemetů jednoduchých typů. Např. pro int: int getint() - relativní čtení z bufferu. Čte 4 byty z aktuální pozice, vrátí je transformované na hodnotu int. Inkrementuje position o 4, int getint(int index) - totéž, ale absolutně, ByteBuffer putint(int value) - relativní zápis na aktuální pozici, position je inkremetováno o 4, ByteBuffer putint(int index, int value) - totéž, ale absolutně.

Specializovaný pohledový buffer U homogenních dat se místo používání typových metod getxxx a putxxx doporučují tzv. pohledové buffery (view buffer), které jsou zálohovány ByteBufferem. Specializovaný pohledový buffer pro typ int se vytvoří metodou: IntBuffer asintbuffer() Pohledové buffery mají následující výhody: jsou indexovány v typovaných elementech a ne v bytech, mají typované put a get metody pokud je zálohový Bytebuffer přímý, jsou také přímé a tudíž efektivní.

Specializované buffery Pro každý primitivní typ existují specializované buffery. Např.: public abstract class IntBuffer extends Buffer implements Comparable<IntBuffer> Specializované buffery definuje operace absolutní a relativní get a put operace na jeden element nebo nebo na pole elementů. Vytváření specializovaných bufferů: zabalením existujícího pole: static IntBuffer wrap(int[] array) - vytvoří buffer zálohovaný zadaným polem, přímou alokací: static IntBuffer allocate(int capacity) vytvořením pohledu na existující ByteBuffer. Specializované buffery mohou být přímé nebo nepřímé.

Kanály Kanály jsou reprezentanty entit, které umožňují čtení a zápis dat (obdoba streamů v java.io) jako jsou soubory, hardwarová zařízení, síťové sokety atp.: interface Channel extends Closeable Na rozdíl od streamů mohou být kanály duplexní. Po vytvoření je kanál otevřen. Po uzavření jej nelze znovu otevřít a zavolání operace hodí výjimku ClosedChannelException: boolean isopen() void close() throws IOException Kanály jsou thread-safe.

Kanál pro čtení a zápis Rozhraní ReadableByteChannel a WritableByteChannel definují kanály pro čtení resp zápis. Na kanálu může probíhat pouze jedna čtecí resp. zápisová operace současně: int read(bytebuffer dst) throws IOException - čte posloupnost bytů z kanálu do bufferu. Operace se pokusí přečíst až dst.remaining() bytů. Vrací skutečný počet přečtených bytů a bufferu position je o tuto hodnotu inkremetována. V blokovacím módu přečte alespoň jeden byte. int write(bytebuffer src) throws IOException - pokusí se zapsat do kanálu blok src.remaining() bytů z bufferu. Počet zapsaných bytů závisí na typu kanálu (Např. SocketChannel v neblokovacím módu zapíše pouze tolik bytů, kolik se aktuálně vejde do výstupního bufferu.

Třída FileChannel Kanál pro čtení, zápis, mapování a manipulaci se soubory. Kanál se vytváří operací getchannel nad objektem FileInputStream, FileOutputStream resp. RandomAccessFile. long position() throws IOException FileChannel position(long newposition) throws IOException - vrací resp. nastavuje pozici kanálu v souboru od které se provádí čtení resp. zápis, long size() throws IOException FileChannel truncate(long size) throws IOException - vrátí resp. nastaví velikost souboru, void force(boolean metadata) throws IOException - způsobí okamžitý zápis dat do souboru.

Kopírování souborů static void copy(file infile, File outfile) throws IOException { FileInputStream fin = new FileInputStream(infile); FileOutputStream fout = new FileOutputStream(outfile); FileChannel fcin = fin.getchannel(); FileChannel fcout = fout.getchannel(); ByteBuffer buffer = ByteBuffer.allocate(1024); // ByteBuffer buffer = ByteBuffer.allocateDirect(1024); while (true) { buffer.clear(); int r = fcin.read( buffer ); if (r==-1) { break; buffer.flip(); fcout.write( buffer );

Třída FileChannel II MappedByteBuffer map(filechannel.mapmode mode, long position, long size) throws IOException - namapuje zadaný region souboru přímo do paměti. Chování kanálu je dáno hodnotou parametru mode (MapMode. READ_ONLY, MapMode.READ_WRITE, MapMode. PRIVATE) FileLock trylock(long position, long size, boolean shared) throws IOException - neblokovací pokus získat zámek pro zadaný region souboru, FileLock lock(long position, long size, boolean shared) throws IOException - blokovací operace pro získání zámku.

Použití mapování private static int sum(bytebuffer bb) { int sum = 0; while (bb.hasremaining()) { if ((sum & 1)!= 0) sum = (sum >> 1) + 0x8000; else sum >>= 1; sum += bb.get() & 0xff; sum &= 0xffff; return sum; private static int sum(file f) throws IOException { FileInputStream fis = new FileInputStream(f); FileChannel fc = fis.getchannel(); sz = (int)fc.size(); MappedByteBuffer bb = fc.map(filechannel.mapmode.read_only, 0, sz); return sum(bb);

SelectableChannel Abstraktní třída SelectableChannel je kanál, který může být testován na připravenost provést nějakou operaci - např. čtení dat. SelectableChannel musí být napřed registrován u objektu Selector: final SelectionKey register(selector sel, int ops) throws ClosedChannelException - registruje kanál u zadaného selektoru a vrací selekční klíč. Parametr ops určuje jednotlivými bity množinu operací, které kanál nabízí (read, write, connect, accept). Konkrétní podtřídy jsou DatagramChannel, ServerSocketChannel, SocketChannel.

Třída Selector Multiplexor zaregistrovaných kanálů. Vytváří se faktorovou metodou: static Selector open() throws IOException Metody: int select(long timeout) throws IOException - blokovací operace detekující kanály, které jsou připravené provést I/O operaci. Vrací nenulový počet připravených kanálů. int selectnow() throws IOException - neblokovací operace se stejnou funkcí, která však může vrátit 0. public abstract Set<SelectionKey> selectedkeys() - vrací množinu klíčů připravených kanálů.

SelectionKey Objekty SelectionKey (selekční klíč) reprezentují registraci kanálů u selektoru. Selekční klíče jsou vytvořeny registrační metodou selektoru: register. Selekční klíč obsahuje dvě množiny operací: interest_set - operace, na které budou testovány kanály selekční metodou selektoru. Operace jsou zadány při registraci kanálu a mohou být později změněny metodou interestops(int), ready-set - operace, které je kanál aktuálně připraven vykonat.

NIO Server public class NioServer implements Runnable { private InetAddress hostaddress; private int port; private ServerSocketChannel serverchannel; private Selector selector; private ByteBuffer readbuffer = ByteBuffer.allocate(8192); public NioServer(InetAddress hostaddress, int port) throws IOException { this.hostaddress = hostaddress; this.port = port; this.selector = this.initselector(hostaddress, port);

Vytvoření selektoru private Selector initselector(inetaddress hostaddress, int port;) throws IOException { Selector socketselector = SelectorProvider.provider().openSelector(); this.serverchannel = ServerSocketChannel.open(); serverchannel.configureblocking(false); InetSocketAddress isa = new InetSocketAddress(this.hostAddress, this.port); serverchannel.socket().bind(isa); serverchannel.register(socketselector, SelectionKey.OP_ACCEPT); return socketselector;

Server run public void run() { while (true) { try { int n = this.selector.select(); Iterator<SelectionKey> selectedkeys = this.selector.selectedkeys().iterator(); while (selectedkeys.hasnext()) { SelectionKey key = selectedkeys.next(); selectedkeys.remove(); if (!key.isvalid()) continue; if (key.isacceptable()) this.accept(key); else if (key.isreadable()) { this.read(key); catch (Exception e) { e.printstacktrace();

Akceptace klíče private void accept(selectionkey key) throws IOException { ServerSocketChannel serversocketchannel = (ServerSocketChannel) key.channel(); SocketChannel socketchannel = serversocketchannel.accept(); Socket socket = socketchannel.socket(); socketchannel.configureblocking(false); socketchannel.register(this.selector, SelectionKey.OP_READ);

Čtení dat private void read(selectionkey key) throws IOException { SocketChannel socketchannel = (SocketChannel) key.channel(); this.readbuffer.clear(); int numread; try { numread = socketchannel.read(this.readbuffer); catch (IOException e) // The remote forcibly closed the connection, { socketchannel.close(); key.cancel(); return; if (numread == -1) { // Remote entity shut the socket down cleanly. { socketchannel.close(); key.cancel(); return; this.worker.processdata(this, socketchannel, this.readbuffer.array(), numread);