System wejścia/wyjścia

Post on 23-Feb-2016

60 views 1 download

description

System wejścia/wyjścia . Strumienie. - PowerPoint PPT Presentation

Transcript of System wejścia/wyjścia

System wejścia/wyjścia

W większości języków programowania biblioteki wejścia/wyjścia ukrywają szczegóły obsługi poszczególnych mediów pod abstrakcją strumienia (ang. stream). Strumienie są używane zarówno do wysyłania/zapisywania jak i pobierania/odczytywania porcji danych. Główną zaletą takiego podejścia jest jego uniwersalność.

Strumienie

1. InputStream i Reader reprezentują strumienie danych wejściowych, a OutputStream i Writer strumienie danych wyjściowych

2. Para InputStream i OutputStream jest przeznaczona do obsługi danych binarnych.

3. Reader i Writer dodano do języka w wersji 1.1 i służą do obsługi danych znakowych.

W Javie hierarchia strumieni oparta jest o cztery klasy:

1. InputStream, 2. OutputStream

1. Reader 2. Writer.

pliku, tablicy bajtów/znaków, obiekcie String oraz łączu (ang. pipe) służącym do komunikacji

procesów.

Strumienie ujednolicają obsługę poszczególnych rodzajów mediów. Standardowe biblioteki Javy zawierają klasy reprezentujące strumienie wejściowe i wyjściowe na:

Typy strumieniPodklasy InputStream i

OutputStreamPodklasy Reader i

Writer Opis

FileInputStream i FileOutputStream FileReader i FileWriter

Pozwalają odczytywać i zapisywać pliki dyskowe. Jako parametr konstruktora przekaż nazwę pliku dyskowego lub

wskazujący go obiekt File. Tworząc obiekt wyjściowy, jako drugi argument konstruktora,

możesz przekazać wartość logicznią określającą czy zamiast zamazywać

istniejący plik dopisywać kolejne dane na jego końcu.

ByteArrayInputStream i ByteArrayOutputStream

CharArrayReader i CharArrayWriter

Bufor w pamięci oparty na tablicy odpowiednio bajtów lub znaków. Tworząc obiekt wejściowy, przekaż konstruktorowi tablicę, na której ma być oparty. Tworząc obiekt wyjściowy, przekaż konstruktorowi

początkowy rozmiar bufora.

Typy strumieni

Podklasy InputStream i OutputStream

Podklasy Reader i Writer Opis

StringBufferInputStream (nie ma odpowiednika do

zapisu)

StringReader i StringWriter

Bufor w pamięci oparty na napisie String (implementacja posługuje się obiektem

StringBuffer). Tworząc obiekt wejściowy, przekaż konstruktorowi napis, na którym ma

być oparty. Tworząc obiekt wyjściowy przekaż konstruktorowi początkowy rozmiar bufora. Zaleca się używanie klas z hierarchii Reader/Writer. StringBufferInputStream jest

oznaczony jako deprecated.

PipedInputStream i PipedOutputStream

PipedReader i PipedWriter

Łącze do komunikacji między procesami. Przy pomocy konstruktora

bezparametrowego należy najpierw utworzyć obiekt jednego rodzaju (wejściowy lub

wyjściowy), a następnie przekazać go jako parametr konstruktora obiektu drugiego rodzaju (odpowiednio wyjściowego lub

wejściowego). Strumienie zostaną połączone łączem, które będzie przesyłać dane od strumienia wyjściowego do wejściowego.

Strumień binarny można przekształcić na strumień znakowy. Służą do tego klasy InputStreamReader i OutputStreamWriter. Taka konwersja czasami jest bardzo przydatna, np. podczas kompresji i dekompresji danych.

Konwersja między strumieniami binarnymi i znakowymi

Wzorzec dekoratora polega na opakowaniu oryginalnej klasy w nową klasę "dekorującą". Zwykle przekazuje się oryginalny obiekt jako parametr konstruktora dekoratora, metody dekoratora wywołują metody oryginalnego obiektu i dodatkowo implementują nową funkcjonalność.

Wzorzec projektowy Dekorator

Strumienie można wykorzystać jedynie w podstawowy sposób – odczytując lub zapisując poszczególne bajty lub znaki. Jeśli chcemy dodać nową funkcjonalność do strumieni, np. możliwość buforowania lub kompresji musimy nasz podstawowy egzemplarz strumienia przekazać do obiektu zwanego dekoratorem. Dekorator implementuje ten sam interfejs lub rozszerza tę samą klasę bazową, którą rozszerza dekorowany obiekt. Dzięki temu można go używać zamiast obiektu oryginalnego. Poszczególne metody dekoratora wywołują metody oryginalnego obiektu, a w między czasie dodają nową funkcjonalność.

Wzorzec projektowy Dekorator – kaskadowe łączenie strumieni

Przykłądowe klasy dekorujące IO

Podklasy InputStream i OutputStream

Podklasy Reader i Writer Opis

BufferedInputStream i BufferedOutputStream

BufferedReader i BufferedWriter

Operacje na strumieniu stają się buforowane. W większości przypadków skutkuje to

znaczącym wzrostem efektywności. Zamiast wykonywać wiele drobnych operacji na

strumieniu, np. wiele razy odczytywać/zapisywać z pliku dyskowego małe porcje danych. Dekorator odczytuje większą porcję na zapas lub zapamiętuje

dane, które mają być wysłane do strumienia dopóki nie uzbiera się ich dostateczna ilość.

PrintStream PrintWriterDodają wiele nowych metod pozwalających

zapisywać do strumienia dane w sposób

czytelny dla człowieka.

W Javie do standardowego wyjścia/wejścia mamy dostęp poprzez zmienne statyczne klasy System

System.out i System.err (typu PrintStream)

System.in (typu InputStream)

Standardowe wejście/wyjście

1. setIn(InputStream)2. setOut(PrintStream)3. setErr(PrintStream)

Przekierowywanie standardowego wejścia/wyjścia

Do przekierowywania używamy statycznych metod z klasy System

W Javie 1.4 dodano "nowe" biblioteki wejścia/wyjścia (ang. new I/O). Są one zebrane w pakietach java.nio.*

Głównym celem przy opracowywaniu nowych bibliotek był wzrost prędkości działania

Jeżeli nie zależy nam na osiągnięciu maksymalnej możliwej prędkości działania wejścia/wyjścia, dotychczasowe "stare" biblioteki są nadal zalecana.

Nowe wejście/wyjście

Serializacja

Serializacja - przekształcanie obiektów na postać binarną lub znakową (np. XML) w sposób, który umożliwia ich późniejsze odtworzenie

Deserializacja – proces odwrotnyZastosowania: Zachowywanie stanu obiektu w pliku Przesyłanie obiektu strumieniami,

np. przez sieć

Wprowadzenie

Interfejs Serializable – wymagana jest jego implementacja,

ObjectOutputStream, ObjectInputStream - klasy umożliwiające zapis i odczyt serializowanych obiektów,

Zapis – metoda writeObject (Object o) Odczyt – metoda readObject (), nie

wywołuje konstruktora obiektu, Wielokrotne referencje do obiektu –

tylko jeden egzemplarz zapisany

Serializacja obiektu

class A implements Serializable {public A(int n) { num = n; System.out.println("Konstruuję obiekt klasy A"); }public String toString() { return "" + num; }int num;

public static void main(String[] args) {A a = new A(42); System.out.println(a);ObjectOutputStream out = new ObjectOutputStream(

new FileOutputStream("plik.o"));out.writeObject(a); out.close();ObjectInputStream in = new ObjectInputStream(new

FileInputStream("plik.o"));A a1 = (A) in.readObject(); in.close(); System.out.println(a1); }}

Serializacja obiektu - przykład

Wynik działania:Konstruuję obiekt klasy A4242

Składowe transient – atrybuty wyłączone z domyślnego systemu serializacji,

Metody writeObject() i readObject() – umożliwiają zastąpienie domyślnych metod serializacji własnym kodem

Kontrola serializacji

class A implements Serializable {int num;transient String str;public A(int n, String s) {num = n; str = s;}public String toString {return num + ” ” + str;}

}

public static void main(String[] args) {A a1 = new A (42, ”napis”), a2;System.out.println(a1);// zapis i odczyt w taki sam sposóbout.writeObject(a1);a2 = (A) in.readObject();System.out.println(a2);

}

Transient - przykład

Wynik działania:42 napis42 null

class A implements Serializable {int num;transient String str;public A(int n, String s) {num = n; str = s;}public String toString {return num + ” ” + str;}

private void writeObject(ObjectOutputStream oos) throws IOException {oos.defaultWriteObject(); oos.writeObject(str);

}private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {

ois.defaultReadObject(); str = (String) ois.readObject();}

}

writeObject(), readObject()

Wynik działania:42 napis42 napis

Rozszerzenie interfejsu Serializable, Metody: readExternal(), writeExternal(),

interfejs deklaruje je jako publiczne Brak możliwości korzystania z domyślnego

systemu serializacji (można jednak przesłać obiekt do metody writeObject() )

W trakcie deserializacji wywołanie domyślnego konstruktora

Interfejs Externalizable

Problem: wczytanie z pliku obiektu nowszej lub starszej wersji klasy

Domyślne zachowanie Javy: zgłoszenie wyjątku InvalidClassException

Rozwiązanie: atrybutstatic final long serialVersionUID

Atrybuty usunięte z klasy, a zawarte w pliku są ignorowane; nowe atrybuty mają wartości domyślne dla swojego typu

Wersjonowanie

XMLEncoder, XMLDecoder – klasy z pakietu java.beans, umożliwiające zapis do XML

Serializowane obiekty powinny być zgodne ze specyfikacją JavaBeans:◦ Publiczna klasa,◦ Publiczny, bezparametrowy konstruktor,◦ Metody get i set dla każdego atrybutu

Implementacja interfejsu Serializable nie jest wymagana

Serializacja do XML

public class A {int num;String str;public A(){}public A(int n, String s) {num = n; str = s;}public int getNum() {return num;}public void setNum(int n) {num = n;}public String getStr() {return str;}public void setStr(String s) {str = s;}public String toString() {return num + " " + str;}

public static void main(String[] args) throws FileNotFoundException{A a = new A(42, "napis"), a1; System.out.println(a);XMLEncoder out = new XMLEncoder(new FileOutputStream("plik.xml"));out.writeObject(a); out.close();

XMLDecoder in = new XMLDecoder(new FileInputStream("plik.xml"));a1 = (A) in.readObject(); in.close(); System.out.println(a1);}}

XML- przykładWynik działania:42 napis42 napis

Wynikowy plik XML:<?xml version="1.0" encoding="UTF-8"?> <java version="1.6.0_17" class="java.beans.XMLDecoder">

<object class="A"> <void property="num">

<int>42</int> </void> <void property="str">

<string>napis</string> </void>

</object> </java>

XML- przykład