• Nie Znaleziono Wyników

Programowanie Obiektowe Java

N/A
N/A
Protected

Academic year: 2021

Share "Programowanie Obiektowe Java"

Copied!
148
0
0

Pełen tekst

(1)

Programowanie Obiektowe

Java

Małgorzata Janik

Zakład Fizyki Jądrowej

(2)

Operacje wejścia-wyjścia

strumienie

(3)

Pakiety IO

Java dostarcza dwóch podstawowych pakietów (z podpakietami), służących do przeprowadzania operacji wejścia-wyjścia:

java.io

java.nio

Pakiet java.io zawiera przede wszystkim klasy, które pozwalają operować na strumieniach danych.

W pakiecie java.nio ("Java new input-output", w skrócie NIO)

wprowadzono dodatkowe środki wejścia-wyjścia, takie jak kanały, bufory i selektory

Mimo nazwy ("new input-output") środki te nie zastępują klas strumieniowych.

Służą przede wszystkim do zapewnienia wysokiej efektywności i elastyczności programów, które w bardzo dużym stopniu obciążone są operacjami wejścia- wyjścia. W szczególności dotyczy to serwerów, które muszą równolegle obsługiwać ogromną liczbę połączeń sieciowych.

(4)

Programowanie Obiektowe (Wykład) Małgorzata Janik (WF PW)

Pakiety IO

Zródło: http://edu.pjwstk.edu.pl/wyklady/poj/scb/Strumienie/Strumienie.html

Java dostarcza dwóch podstawowych pakietów (z podpakietami), służących do przeprowadzania operacji wejścia-wyjścia:

java.io

java.nio

Pakiet java.io zawiera przede wszystkim klasy, które pozwalają operować na strumieniach danych.

W pakiecie java.nio ("Java new input-output", w skrócie NIO)

wprowadzono dodatkowe środki wejścia-wyjścia, takie jak kanały, bufory i selektory

Mimo nazwy ("new input-output") środki te nie zastępują klas strumieniowych.

Służą przede wszystkim do zapewnienia wysokiej efektywności i elastyczności programów, które w bardzo dużym stopniu obciążone są operacjami wejścia- wyjścia. W szczególności dotyczy to serwerów, które muszą równolegle obsługiwać ogromną liczbę połączeń sieciowych.

Stosunkowo niedawno (w Javie 7) doszedł

również pakiet NIO.2...

(5)

Image by Thalpha 

Strumienie

(6)

Programowanie Obiektowe (Wykład) Małgorzata Janik (WF PW)

Strumienie

Strumień danych jest pojęciem abstrakcyjnym, logicznym.

Oznacza ciąg danych, właśnie „strumień”, do którego dane mogą być dodawane i z którego dane mogą być pobierane.

Przy czym:

strumień związany jest ze źródłem lub odbiornikiem danych,

źródło lub odbiornik mogą być dowolne: plik, pamięć, URL, gniazdo, potok ...

strumień służy do zapisywania/odczytywania informacji - dowolnych danych,

program:

kojarzy strumień z zewnętrznym źródłem/odbiornikiem,

otwiera strumień,

dodaje lub pobiera dane ze strumienia,

zamyka strumień.

przy czytaniu lub zapisie danych z/do strumienia mogą być wykonywane dodatkowe operacje (np. buforowanie, kodowanie/dekodowanie, kompresja/dekompresja)

w Javie dostarczono szereg klas reprezentujących strumienie; hierarchia tych klas

pozwala na programowanie w sposób abstrahujący od konkretnych źródeł i odbiorników.

Żródło: http://edu.pjwstk.edu.pl/wyklady/poj/scb/Strumienie/Strumienie.html

(7)

Klasy strumieni

(8)

Programowanie Obiektowe (Wykład) Małgorzata Janik (WF PW)

Strumienie wejściowe / wyjściowe

Strumień wejściowy

(9)

Strumienie wejściowe / wyjściowe

Na strumieniach możemy wykonywać dwie podstawowe operacje:

odczytywanie danych

z pliku, z konsoli, z tablicy, z zewnętrznego urządzenia, z gniazda...

zapisywanie danych

do pliku, na ekran, do gniazda...

Z tego punktu widzenia możemy mówić o strumieniach wejściowych i wyjściowych.

I odpowiednio do tego – Java wprowadza dwie rozłączne hierarchie klas strumieniowych: klasy strumieni wejściowych i klasy strumieni

wyjściowych.

(10)

Programowanie Obiektowe (Wykład) Małgorzata Janik (WF PW)

Strumienie wejściowe / wyjściowe

Ilość wejściowych / wyjściowych strumieni w programie jest nieograniczona:

od 0 do N.

(11)

https://www.javatpoint.com/java-

Strumienie powiązane z konsolą

W Javie istnieją strumienie tworzone automatycznie – powiązane z konsolą:

System.out: strumień standardowego wyjścia

System.in: strumień stndardowego wejścia

System.err: strumień standardowego wyjścia błędu

Kod do wypisania informacji / błędu w konsoli:

Kod do wczytania informacji z konsoli:

System.out.println("simple message");  

System.err.println("error message");  

int i=System.in.read();//returns ASCII code of 1st character   System.out.println((char)i);//will print the character  

(12)

Programowanie Obiektowe (Wykład) Małgorzata Janik (WF PW)

Strumienie bajtowe / znakowe

Pobranie/zapis danych może dotyczyć określonych atomistycznych (minimalnie rozróżnialnych w trakcie operacji) „porcji danych”.

Mogą to być

Bajty

Znaki (standard w Javie to Unikod, znak Unikodu jest złożony z dwóch bajtów)

Wobec tego powstają kolejne dwie rozłączne hierarchie klas strumieniowych:

klasy strumieni bajtowych („atomem” operacji we-wy jest bajt),

klasy strumieni znakowych („atomem” są znaki Unikodu – 2 bajty).

Przy przetwarzaniu tekstów należy korzystać ze strumieni znakowych ze względu na to, iż w trakcie czytania/pisania wykonywane są

odpowiednie operacje kodowania/dekodowania ze względu na stronę kodową właściwą dla źródła/odbiornika

Żródło: http://edu.pjwstk.edu.pl/wyklady/poj/scb/Strumienie/Strumienie.html

(13)

Strumienie znakowy / bajtowy

Strumień wejściowy

znakowy Strumień wejściowy

bajtowy

Nie można ich traktować tak samo…

(14)

Programowanie Obiektowe (Wykład) Małgorzata Janik (WF PW)

Wejście Wyjście

Strumień bajtowy InputStream OutputStream

Strumień znakowy Reader Writer

Rodzaje strumieni

Zatem w Javie mamy 4 podstawowe rodzaje strumieni:

– Wejścia / wyjścia

– Bajtowe / znakowe

(15)

Klasy strumieni

InputStream, OutputStream, Reader, Writer 4 klasy strumieni abstrakcyjnych→ 4 klasy strumieni abstrakcyjnych

(16)

Programowanie Obiektowe (Wykład) Małgorzata Janik (WF PW)

Rodzaje strumieni

Powyższe klasy strumieni to klasy abstrakcyjne, zatem bezpośrednio nie można tworzyć obiektów tych klas.

Dostarczają one natomiast podstaw dla wszystkich innych klas strumieniowych oraz paru ogólnych użytecznych (choć bardzo podstawowych) metod.

Metody te umożliwiają m.in.

czytanie - read(..) (bajtów, znaków) - różne wersje tej (przeciążonej) metody pozwalają na

przeczytanie jednego bajtu ze strumienia bajtowego lub znaku ze strumienia znakowego albo całej porcji bajtów/znaków,

zapisywanie - write(..) (bajtów/znaków) - różne wersje tej (przeciążonej) metody pozwalają

zapisywac pojedyńcze bajty/znaki lub tablice bajtów/znaków, a w przypadku strumieni znakowych również napisy (obiekty klasy String),

pozycjonowanie strumieni (metody skip(..), mark(..), reset() ) - każdy strumień może być traktowany jako sekwencja bajtów/znaków, czytanie i zapisywanie zawsze dotyczy bieżącej pozycji tej

sekwencji; po wykonaniu operacji czytania lub zapisu bieżąca pozycja zwiększa się o jeden; metody pozycjonowania pozwalają zmieniać bieżącą pozycję.

zamykanie strumieni (metoda close()) - strumień zawsze należy zamknąć po zakończeniu operacji na nim.

Metody te są zazwyczaj odpowiednio przedefiniowane w klasach dziedziczących; polimorfizm zapewnia ich oszczędne i właściwe użycie.

Wejście Wyjście

Strumień bajtowy InputStream OutputStream

Strumień znakowy Reader Writer

(17)

Przykład

Klasa która kopiuje strumień wejściowy do strumienia wyjściowego

Uwaga: metoda read() zwraca liczbę całkowitą, reprezentującą kolejny znak ze

strumienia znakowego (lub bajt ze strumienia bajtowego) albo wartość -1 gdy czytanie sięga poza koniec pliku.

class Stream {

static void copy(InputStream in, OutputStream out) throws IOException { int c;

while ((c = in.read()) != -1) out.write(c);

}

static void copy(Reader in, Writer out) throws IOException { int c;

while ((c = in.read()) != -1) out.write(c);

} }

Klasy abstrakcyjne Wejście Wyjście

Strumień bajtowy InputStream OutputStream

Strumień znakowy Reader Writer

(18)

Programowanie Obiektowe (Wykład) Małgorzata Janik (WF PW)

Przykład

Klasa która kopiuje strumień wejściowy do strumienia wyjściowego

Uwaga: metoda read() zwraca liczbę całkowitą, reprezentującą kolejny znak ze

strumienia znakowego (lub bajt ze strumienia bajtowego) albo wartość -1 gdy czytanie sięga poza koniec pliku.

Możemy teraz użyć metody copy wobec dowolnych strumieni z odpowiednich konkretnych klas hierarchii klas strumieniowych, np.

By kopiowanie miało sens input musi być powiązane z konkretnym źródłem danych, a output – konkretnym odbiornikiem danych.

class Stream {

static void copy(InputStream in, OutputStream out) throws IOException { int c;

while ((c = in.read()) != -1) out.write(c);

}

static void copy(Reader in, Writer out) throws IOException { int c;

while ((c = in.read()) != -1) out.write(c);

} }

Stream.copy(input, output);

(19)

Przykład

Klasa która kopiuje strumień wejściowy do strumienia wyjściowego

Uwaga: metoda read() zwraca liczbę całkowitą, reprezentującą kolejny znak ze

strumienia znakowego (lub bajt ze strumienia bajtowego) albo wartość -1 gdy czytanie sięga poza koniec pliku.

Możemy teraz użyć metody copy wobec dowolnych strumieni z odpowiednich konkretnych klas hierarchii klas strumieniowych, np.

By kopiowanie miało sens input musi być powiązane z konkretnym źródłem danych, a output – konkretnym odbiornikiem danych.

class Stream {

static void copy(InputStream in, OutputStream out) throws IOException { int c;

while ((c = in.read()) != -1) out.write(c);

}

static void copy(Reader in, Writer out) throws IOException { int c;

while ((c = in.read()) != -1) out.write(c);

} }

Stream.copy(input, output);

Strumień (w którymś momencie) musi być związany z

(20)

Programowanie Obiektowe (Wykład) Małgorzata Janik (WF PW)

Żródło/

odbiornik Strumienie znakowe Strumienie bajtowe

Wejście Wyjście Wejście Wyjście

Pamięć CharArrayWriter CharArrayWriter ByteArrayInputStream ByteArrayOutputStream

String StringReader StringWriter

Potok PipedReader PipedWriter PipedInputStream PipedOutputStream

Plik FileReader FileWriter FileInputStream FileOutputStream

Wymienione wyżej klasy pozwalają na powiązanie strumienia z konkretnym wejściem lub wyjściem.

Wyżej wymienione nie są jednak jedynymi, można tu wspomnieć np. o klasie GZIPInputStream który umożliwia obsługę strumieni spakowanych algorytmem gzip.

Wiązanie strumienia z danymi

źródła źródła

http://tutorials.jenkov.com/java-io/

pipes.html

(21)

Przykład

Chcielibyśmy wczytać informacje z jednego pliku tekstowego i zapisać do innego pliku

Potrzebujemy

Strumienia znakowego na wejściu wczytującego z pliku

Strumienia znakowego na wyjściu, zapisującego do pliku

(22)

Programowanie Obiektowe (Wykład) Małgorzata Janik (WF PW)

Przykład

Chcielibyśmy wczytać informacje z jednego pliku tekstowego i zapisać do innego pliku

Potrzebujemy

Strumienia znakowego na wejściu wczytującego z pliku FileReader

Strumienia znakowego na wyjściu, zapisującego do pliku

FileWriter

(23)

static public void main(String[] args) { try {

FileReader in1 = new FileReader("plik0.txt");

FileWriter out1 = new FileWriter("plik1.txt");

Stream.copy(in1, out1);

in1.close();

out1.close();

} catch(IOException exc) { exc.printStackTrace();

}

Przykład

Chcielibyśmy wczytać informacje z jednego pliku tekstowego i zapisać do innego pliku

Potrzebujemy

Strumienia znakowego na wejściu wczytującego z pliku FileReader

Strumienia znakowego na wyjściu, zapisującego do pliku FileWriter

Konstruktor przyjmuje np.

nazwę / ścieżkę do pliku

Po użyciu strumienie

zawsze zamkykamy!

(24)

Programowanie Obiektowe (Wykład) Małgorzata Janik (WF PW)

static public void main(String[] args) { try {

FileReader in1 = new FileReader("plik0.txt");

FileWriter out1 = new FileWriter("plik1.txt");

Stream.copy(in1, out1);

in1.close();

out1.close();

} catch(IOException exc) { exc.printStackTrace();

}

Przykład

Chcielibyśmy wczytać informacje z jednego pliku tekstowego i zapisać do innego pliku

Potrzebujemy

Strumienia znakowego na wejściu wczytującego z pliku FileReader

Strumienia znakowego na wyjściu, zapisującego do pliku FileWriter

Możemy użyć kopiowania strumieni

zaprezentowanego wcześniej

(25)

Przypomnienie

Klasa która kopiuje strumień wejściowy do strumienia wyjściowego

Uwaga: metoda read() zwraca liczbę całkowitą, reprezentującą kolejny znak ze

strumienia znakowego (lub bajt ze strumienia bajtowego) albo wartość -1 gdy czytanie sięga poza koniec pliku.

Możemy teraz użyć metody copy wobec dowolnych strumieni z odpowiednich konkretnych klas hierarchii klas strumieniowych, np.

By kopiowanie miało sens input musi być powiązane z konkretnym źródłem danych , a output – konkretnym odbiornikiem danych.

class Stream {

static void copy(InputStream in, OutputStream out) throws IOException { int c;

while ((c = in.read()) != -1) out.write(c);

}

static void copy(Reader in, Writer out) throws IOException { int c;

while ((c = in.read()) != -1) out.write(c);

} }

Stream.copy(input, output);

Strumień (w którymś momencie) musi być związany z

(26)

Programowanie Obiektowe (Wykład) Małgorzata Janik (WF PW)

Przykład II

Chcielibyśmy stworzyć strumień ze Stringa i zapisać do pliku

Strumienia znakowego na wejściu używającego zadeklarowanego Stringa (z pamięci)

Strumienia znakowego na wyjściu, zapisującego do pliku

(27)

Żródło/

odbiornik Strumienie znakowe Strumienie bajtowe

Wejście Wyjście Wejście Wyjście

Pamięć CharArrayWriter CharArrayWriter ByteArrayInputStream ByteArrayOutputStream

StringReader StringWriter

Potok PipedReader PipedWriter PipedInputStream PipedOutputStream

Plik FileReader FileWriter FileInputStream FileOutputStream

Wiązanie strumienia z danymi

– Strumienia znakowego na wejściu używającego

zadeklarowanego Stringa

(28)

Żródło/

odbiornik Strumienie znakowe Strumienie bajtowe

Wejście Wyjście Wejście Wyjście

Pamięć CharArrayWriter CharArrayWriter ByteArrayInputStream ByteArrayOutputStream

StringReader StringWriter

Potok PipedReader PipedWriter PipedInputStream PipedOutputStream

Plik FileReader FileWriter FileInputStream FileOutputStream

Wiązanie strumienia z danymi

– Strumienia znakowego na wejściu używającego zadeklarowanego Stringa

– Strumienia znakowego na wyjściu, zapisującego do pliku

(29)

static public void main(String[] args) { try {

String msg = "Ala ma kota";

StringReader in2 = new StringReader(msg);

FileWriter out2 = new FileWriter("plik2.txt");

Stream.copy(in2, out2);

in2.close();

out2.close();

} catch(IOException exc) { exc.printStackTrace();

}

Przykład II

StringReader w konstruktorze

przyjmuje String który ma być źródłem

Chcielibyśmy stworzyć strumień ze Stringa i zapisać do pliku

Strumienia znakowego na wejściu używającego zadeklarowanego Stringa

StringReader

Strumienia znakowego na wyjściu, zapisującego do pliku

FileWriter

(30)

static public void main(String[] args) { try {

String msg = "Ala ma kota";

StringReader in2 = new StringReader(msg);

FileWriter out2 = new FileWriter("plik2.txt");

Stream.copy(in2, out2);

in2.close();

out2.close();

} catch(IOException exc) { exc.printStackTrace();

}

Przykład II

Chcielibyśmy stworzyć strumień ze Stringa i zapisać do pliku

Strumienia znakowego na wejściu używającego zadeklarowanego Stringa

StringReader

Strumienia znakowego na wyjściu, zapisującego do pliku FileWriter

Przy używaniu strumieni ZAWSZE

łapiemy wyjątki IOException!

(31)

Uwagi

Komentarze:

W podanym przykładzie używaliśmy jednej z wersji konstruktorów klas

strumieniowych związanych z plikami podaliśmy jako argument nazwę pliku → 4 klasy strumieni abstrakcyjnych

można także utworzyć strumień plikowy podając jako argument konstruktora referenecję do obiektu klasy File (o tym zaraz)

przy tworzeniu obiektów klas strumieniowych, związanych z plikami, odpowiednie pliki są otwierane;

strumienie wejściowe są otwierane "tylko do odczytu",

strumienie wyjściowe "tylko do zapisu".

strumienie wyjściowe mogą być otwarte w trybie dopisywania (należy użyć konstruktora z drugim argumentem "append mode" = true); w takim przypadku dane będo dopisywane do końca strumienia,

przy operacjach na strumieniach może powstać wyjątek klasy IOException

oznaczający błąd operacji (np. odczytu lub zapisu), a także wyjątki klas pochodnych FileNotFoundException (brak pliku) oraz EOFException (w trakcie operacji

czytania lub pozycjonowania osiągnięto koniec pliku),

Strumienie danych są wykorzystywane przez wiele programów nie tylko do odczytu plików, ale np. do przesyłania danych pomiędzy

poszczególnymi wątkami czy też do sieci.

Nie ma jedynej słusznej metody otwarcia pliku.

Istnieje wiele konstruktorów,

należy dobrać odpowiedni do danej sytuacji.

(32)

Uwagi

Komentarze:

W podanym przykładzie używaliśmy jednej z wersji konstruktorów klas

strumieniowych związanych z plikami podaliśmy jako argument nazwę pliku → 4 klasy strumieni abstrakcyjnych

można także utworzyć strumień plikowy podając jako argument konstruktora referenecję do obiektu klasy File (o tym zaraz)

przy tworzeniu obiektów klas strumieniowych, związanych z plikami, odpowiednie pliki są otwierane;

strumienie wejściowe są otwierane "tylko do odczytu",

strumienie wyjściowe "tylko do zapisu".

strumienie wyjściowe mogą być otwarte w trybie dopisywania (należy użyć konstruktora z drugim argumentem "append mode" = true); w takim przypadku dane będo dopisywane do końca strumienia,

przy operacjach na strumieniach może powstać wyjątek klasy IOException

oznaczający błąd operacji (np. odczytu lub zapisu), a także wyjątki klas pochodnych FileNotFoundException (brak pliku) oraz EOFException (w trakcie operacji

czytania lub pozycjonowania osiągnięto koniec pliku),

Strumienie danych są wykorzystywane przez wiele programów nie tylko do odczytu plików, ale np. do przesyłania danych pomiędzy

poszczególnymi wątkami czy też do sieci.

FileWriter out = new FileWriter("plik.txt");

Plik domyślnie otworzy się “do zapisu”.

Nie ma metody “open”.

(33)

Uwagi

Komentarze:

W podanym przykładzie używaliśmy jednej z wersji konstruktorów klas

strumieniowych związanych z plikami podaliśmy jako argument nazwę pliku → 4 klasy strumieni abstrakcyjnych

można także utworzyć strumień plikowy podając jako argument konstruktora referenecję do obiektu klasy File (o tym zaraz)

przy tworzeniu obiektów klas strumieniowych, związanych z plikami, odpowiednie pliki są otwierane;

strumienie wejściowe są otwierane "tylko do odczytu",

strumienie wyjściowe "tylko do zapisu".

strumienie wyjściowe mogą być otwarte w trybie dopisywania (należy użyć konstruktora z drugim argumentem "append mode" = true); w takim przypadku dane będo dopisywane do końca strumienia,

przy operacjach na strumieniach może powstać wyjątek klasy IOException

oznaczający błąd operacji (np. odczytu lub zapisu), a także wyjątki klas pochodnych FileNotFoundException (brak pliku) oraz EOFException (w trakcie operacji

czytania lub pozycjonowania osiągnięto koniec pliku),

Strumienie danych są wykorzystywane przez wiele programów nie tylko do odczytu plików, ale np. do przesyłania danych pomiędzy

poszczególnymi wątkami czy też do sieci.

Trzeba pamiętać o obsłudze wyjątków!

Należy chociaż wypisać printStackTrace()

który wypisuje w konsoli szczegóły problemu

(34)

Uwagi

Komentarze:

W podanym przykładzie używaliśmy jednej z wersji konstruktorów klas

strumieniowych związanych z plikami podaliśmy jako argument nazwę pliku → 4 klasy strumieni abstrakcyjnych

można także utworzyć strumień plikowy podając jako argument konstruktora referenecję do obiektu klasy File (o tym zaraz)

przy tworzeniu obiektów klas strumieniowych, związanych z plikami, odpowiednie pliki są otwierane;

strumienie wejściowe są otwierane "tylko do odczytu",

strumienie wyjściowe "tylko do zapisu".

strumienie wyjściowe mogą być otwarte w trybie dopisywania (należy użyć konstruktora z drugim argumentem "append mode" = true); w takim przypadku dane będo dopisywane do końca strumienia,

przy operacjach na strumieniach może powstać wyjątek klasy IOException

oznaczający błąd operacji (np. odczytu lub zapisu), a także wyjątki klas pochodnych FileNotFoundException (brak pliku) oraz EOFException (w trakcie operacji

czytania lub pozycjonowania osiągnięto koniec pliku),

Strumienie danych są wykorzystywane przez wiele programów nie tylko do odczytu plików, ale np. do przesyłania danych pomiędzy

poszczególnymi wątkami czy też do sieci.

Strumienie często służą do obsługi plików,

ale nie tylko

(35)

Klasy strumieni

Szare elementy oznaczają związane z konkretnym źródłem/odbiornikiem dyskutowane przed chwilą, → 4 klasy strumieni abstrakcyjnych Białe - klasy przetwarzające (realizujące określone rodzaje przetwarzania) dyskutowane za chwilę.→ 4 klasy strumieni abstrakcyjnych

(36)

Klasy przetwarzające

Samo określenie strumienia często nie wystarcza.

Ciągnąc dalej analogię z hydrobudownictwem na tym etapie mamy już źródło

i rzekę. Teraz czas stawiać zapory i elektrownie.

(37)

Klasy przetwarzające

Samo określenie strumienia często nie wystarcza.

Ciągnąc dalej analogię z hydrobudownictwem na tym etapie mamy już źródło

i rzekę. Teraz czas stawiać zapory i elektrownie.

(38)

Klasy przetwarzające

Ciągnąc dalej analogię z hydrobudownictwem na tym

etapie mamy już źródło i rzekę. Teraz czas stawiać zapory.

Odpowiednikiem zapór są klasy przetwarzające

strumienie, służą one do tego aby nasze strumienie bajtów bądź znaków wykorzystać w użyteczny sposób.

Przykładem są klasy buforujące.

Dzięki temu program może działać szybciej, bo nie musi co

chwilę odwoływać się do danych (np. na dosyć powolnym dysku) a czyta je z bufora.

Życiowym przykładem takiego bufora jest lodówka, która

przechowuje (buforuje) nam kupione w sklepie produkty. Dzięki

niej nie musimy biegać co chwilę do sklepu.

(39)

Klasy przetwarzające

Rodzaj przetwarzania Strumienie znakowe Strumienie bajtowe Buforowanie BufferedReader,

BufferedWriter BufferedInputStream, BufferedOutputStream Filtrowanie FilterReader, FilterWriter FilterInputStream,

FilterOutputStream Konwersja: bajty-znaki InputStreamReader,

OutputStreamWriter

Serializacja obiektów ObjectInputStream,

ObjectOutputStream Czytanie typów prostych z

bajtów DataInputStream,

DataOutputStream

Zliczanie wierszy LineNumberReader LineNumberInputStream

Drukowanie PrintWriter PrintStream

(40)

Klasy przetwarzające

Jak użyć klasy przetwarzającej?

Konstruktory klas przetwarzających mają jako argument referencję do obiektów podstawowych klas abstrakcyjnych hierarchii dziedziczenia (InputSteram, OutputSteram, Reader, Writer).

Dlatego przetwarzanie (automatyczna transformacja) danych jest logicznie oderwana od fizycznego strumienia, stanowi swoistą na niego “nakładkę”.

Zatem zastosowanie klas przetwarzających wymaga:

stworzenia obiektu związanego z fizycznym źródłem/odbiornikiem,

stworzenie obiektu odpowiedniej klasy przetwarzającej, "nałożonego"

na fizyczny strumień.

Żródło: http://edu.pjwstk.edu.pl/wyklady/poj/scb/Strumienie/Strumienie.html

(41)

Klasy przetwarzające

Jak użyć klasy przetwarzającej?

Zastosowanie klas przetwarzających wymaga:

stworzenia obiektu związanego z fizycznym źródłem/odbiornikiem

stworzenie obiektu odpowiedniej klasy przetwarzającej,

"nałożonego" na fizyczny strumień.

Przykład: najpierw trzeba stworzyć strumień wczytujący z pliku, a dopiero potem go zbuforować.

Taki "tasiemcowy" dostęp do zbuforowanych danych powoduje znaczne zwiększenie elastyczności kodu,

jeśli chce się np. tylko zmienić źródło strumienia wystarczy klasę FileInputStream zastąpić inną np. PipedInputStream. Reszty kodu zaś nie trzeba zmieniać..

BufferedInputStream bufferedInputStream 

= new BufferedInputStream(new FileInputStream(from));

(42)

Do czego mogą służyć klasy przetwarzające?

Klasy buforujące

Zmniejszają liczbę fizycznych odwołań do urządzeń zewnętrznych. Przy czytaniu dużych plików tekstowych należy unikać bezpośredniego

czytania za pomocą klasy FileReader. To samo dotyczy zapisu.

Konwersja bajty-znaki

InputStreamReader czyta bajty ze strumienia definiowanego przez InputStream (strumień bajtowy) i zamienia je na znaki (16 bitowe), używając domyślnej lub podanej strony kodowej,

OutputStreamWriter wykonuje przy zapisie konwersję odwrotną.

Czytanie typów prostych z bajtów

DataInputStream i DataOutputStream są strumieniami bajtowymi, ale pozwalają czytać/pisać dane typów pierwotnych (np. short, char, int, float, double, boolean) ze/do strumieni bajtowych.

Żródło: http://edu.pjwstk.edu.pl/wyklady/poj/scb/Strumienie/Strumienie.html

(43)

Do czego mogą służyć klasy przetwarzające?

Serializacja

służy do "utrwalania" obiektów po to, by odtworzyć je w innym kontekście (przy ponownym uruchomieniu programu lub w innym miejscu, np. programie działającym w innym miejscu sieci po

przekazaniu "utrwalonego" obiektu przez socket),

Klasy LineNumber...

zlicza wiersze strumienia przy czytaniu (i pozwala w każdym momencie uzyskać informację o numerze wiersza).

Klasy Print...

zawierają wygodne metody wyjścia (np. println). Niekoniecznie

oznacza to drukowanie fizyczne, często wykorzystywane jest w

powiązaniu z innymi strumieniami po to by łatwo wyprowadzać

informacje.

(44)

Przykład

Buforowanie wczytywanego pliku

– Czytanie linia po linii z pliku tekstowego

FileReader fr = new FileReader("plik.txt");

// tu powstaje związek z fizycznym źródłem

BufferedReader br = new BufferedReader(fr);

// tu dodajemy "opakowanie" umożliwiające buforowanie czytamy wiersz po wierszu

String line;

while ((line = br.readLine()) != null) {

// kolejny wiersz pliku: metoda readLine zwraca wiersz lub null jeśli koniec pliku

// ... tu coś robimy z odczytanym wierszem }

(45)

Przykład

Buforowanie wczytywanego pliku

– Czytanie linia po linii z pliku tekstowego

FileReader fr = new FileReader("plik.txt");

// tu powstaje związek z fizycznym źródłem

BufferedReader br = new BufferedReader(fr);

// tu dodajemy "opakowanie" umożliwiające buforowanie czytamy wiersz po wierszu

String line;

while ((line = br.readLine()) != null) {

// kolejny wiersz pliku: metoda readLine zwraca wiersz lub null jeśli koniec pliku

// ... tu coś robimy z odczytanym wierszem }

(46)

Przykład

Buforowanie wczytywanego pliku

– Czytanie linia po linii z pliku tekstowego

BufferedReader br = new BufferedReader(new FileReader("plik.txt"));

// tu powstaje związek z fizycznym źródłem oraz dodajemy "opakowanie"

umożliwiające buforowanie czytamy wiersz po wierszu String line;

while ((line = br.readLine()) != null) {

// kolejny wiersz pliku: metoda readLine zwraca wiersz lub null jeśli koniec pliku

// ... tu coś robimy z odczytanym wierszem }

(47)

Przykład II

Przykład buforowania: program, czytający plik tekstowy i zapisujący jego zawartość do innego pliku tekstowego wraz z numerami wierszy.

class Lines {

public static void main(String args[]) { try {

FileReader fr = new FileReader(args[0]);

LineNumberReader lr = new LineNumberReader(fr);

BufferedWriter bw = new BufferedWriter(

new FileWriter(args[1]));

String line;

while ((line = lr.readLine()) != null) {

bw.write( lr.getLineNumber() + " " + line);

bw.newLine();

}

lr.close();

bw.close();

} catch(IOException exc) {

System.out.println(exc.toString());

System.exit(1);

}

klasa LineNumberReader dziedziczy klasę BufferedReader,

dając możliwość uzyskania numeru wiersza

(metoda getLineNumber())

(48)

Przykład II

Przykład buforowania: program, czytający plik tekstowy i zapisujący jego zawartość do innego pliku tekstowego wraz z numerami wierszy.

class Lines {

public static void main(String args[]) { try {

FileReader fr = new FileReader(args[0]);

LineNumberReader lr = new LineNumberReader(fr);

BufferedWriter bw = new BufferedWriter(

new FileWriter(args[1]));

String line;

while ((line = lr.readLine()) != null) {

bw.write( lr.getLineNumber() + " " + line);

bw.newLine();

}

lr.close();

bw.close();

} catch(IOException exc) {

System.out.println(exc.toString());

System.exit(1);

} } }

klasa LineNumberReader dziedziczy klasę BufferedReader,

dając możliwość uzyskania numeru wiersza (metoda getLineNumber())

przy zamknięciu wyjściowego strumienia buforowanego zawartość bufora jest zapisywana

do strumienia; istnieje też metoda void flush( ), zapisujące dane które pozostały w buforze

a nie zostały jeszcze zapisane w miejscu przeznaczenia;

takie "ręczne" opróżnianie bufora jest czasem przydatne.

(49)

Przykład II

Przykład buforowania: program, czytający plik tekstowy i zapisujący jego zawartość do innego pliku tekstowego wraz z numerami wierszy.

class Lines {

public static void main(String args[]) { try {

FileReader fr = new FileReader(args[0]);

LineNumberReader lr = new LineNumberReader(fr);

BufferedWriter bw = new BufferedWriter(

new FileWriter(args[1]));

String line;

while ((line = lr.readLine()) != null) {

bw.write( lr.getLineNumber() + " " + line);

bw.newLine();

}

lr.close();

bw.close();

} catch(IOException exc) {

System.out.println(exc.toString());

System.exit(1);

}

Wyjątki:

łapiemy IOException

(50)

Przykład II

Przykład buforowania: program, czytający plik tekstowy i zapisujący jego zawartość do innego pliku tekstowego wraz z numerami wierszy.

class Lines {

public static void main(String args[]) { try {

FileReader fr = new FileReader(args[0]);

LineNumberReader lr = new LineNumberReader(fr);

BufferedWriter bw = new BufferedWriter(

new FileWriter(args[1]));

String line;

while ((line = lr.readLine()) != null) {

bw.write( lr.getLineNumber() + " " + line);

bw.newLine();

}

lr.close();

bw.close();

} catch(IOException exc) {

System.out.println(exc.toString());

System.exit(1);

} } }

zastosowanie metody newLine() z klasy BufferedWriter pozwala w niezależny od platformy systemowej

sposób zapisywać separatory wierszy

(51)

Klasy strumieni

Szare elementy oznaczają związane z konkretnym źródłem/odbiornikiem, Białe - klasy przetwarzające (realizujące określone rodzaje przetwarzania).

(52)

Inne ważne klasy IO/NIO File

Path

Przykłady

(53)

File

File, w przeciwieństwie do tego, co sugeruje nazwa, nie reprezentuje pliku

Reprezentuje nazwę (wraz ze ścieżką) danego pliku albo nazwę (wraz ze ścieżką) zbioru plików w katalogu

Konstruktory klasy file:

File(String pathname) – tworzy obiekt File na podstawie ścieżki podanej jako napis (to może być plik lub katalog)

File(File parent, String child) – tworzy obiekt File na podstawie innego obiektu File (zawierającego zbiór plików) i nazwy konkretnego pliku

File(String parent, String child) – tworzy obiekt File na podstawie ścieżki podanej jako napis (zawierającej zbiór plików) i nazwy konkretnego pliku

File(URI uri) – URI oznacza referencję Uniform Resource Identifier,

pozwala m.in linkować do źródeł zewnętrznych (np. z internetu).

(54)

File

Wybrane metody

public String getName() - zwraca nazwę pliku lub katalogu w postaci napisu

public String getPath() - zwraca ścieżkę w postaci napisu

public boolean isFile() - sprawdza, czy podany obiekt File jest zwykłym plikiem (a nie, np. katalogiem)

public String[] list() - żeby wyciągnąć nazwy pojedynczych plików ze zbioru używamy list() która zwraca tablicę

znaków

public boolean delete(): usuwa plik albo katalog na który wskazuje dany obiekt File

https://www.tutorialspoint.com/java/java_file_class.htm

(55)

File Przykład

import java.io.File;

public class FileDemo {

public static void main(String[] args) { File f = null;

String[] strs = { "test1.txt", "test2.txt" };

try {

// dla kazdego string w tablicy strs for (String s : strs) {

// stworz nowy obiekt File f = new File(s);

// true jesli wykonywalny

boolean bool = f.canExecute();

// znajdz sciezke absolutna

String a = f.getAbsolutePath();

// wypisz sciezke absolutna z informacja o wykonywalnosci System.out.print(a);

System.out.println(" is executable: " + bool);

}

} catch (Exception e) {

// jesli pojawi sie IO exception e.printStackTrace();

}

}

Wyjątki:

łapiemy IOException

Tworzymy nowy obiekt File

Wyciągamy dane o pliku

FileDemo.java

(56)

Path

Przed Javą SE 7 zawsze używano java.io.File

Ze względu na powszechność jej użycia, prawdopodobnie nigdy nie zostanie całkowicie wycofana / zastąpiona

Jednak wraz z Javą SE 7 powstała nowa klasa, Path, która robi to samo co File, tylko lepiej i więcej

Mamy dostęp do metadanych takich jak uprawnienia

(permissions) danego pliku, wsparcie dla linków symbolicznych, lepiej sobie radzi z bardzo dużymi katalogami, metoda

rename(..) działa tak samo na różnych platformach,

dokładniejsze informacje dotyczące sytuacji wyjątkowych

Ogólne zasady:

Dla nowych projektów lepiej używać Path

Na tą chwilę File nie można uznać za “przestarzałe”

(57)

Path

File Path

file = new File("path/to/file.txt") path = Paths.get("path/to/file.txt")

file = new File(parentFile, "file.txt") path = parentPath.resolve("file.txt")

file.getFileName() path.getFileName().toString()

file.delete() Files.delete(path)

// Microsoft Windows syntax

Path path = Paths.get("C:\\home\\joe\\foo");

// Linux syntax

Path path = Paths.get("/home/joe/foo");

path.toFile() file.toPath()

(58)

JFileChooser

JFileChooser chooser = new JFileChooser();

chooser.showDialog(null, "Wybierz");

chooser.getSelectedFile();

(59)

JFileChooser

Okienko pozwalające wybrać pik

public class JFileChooserExample {

public static void main(String[] args) { JFileChooser chooser = new JFileChooser();

chooser.setDialogTitle("Wybierz plik");

//Otwarcie okienka; metoda blokuje się do czasu wybrania pliku lub zamknięcia okna

int result = chooser.showDialog(null, "Wybierz");

if (JFileChooser.APPROVE_OPTION == result){

System.out.println("Wybrano plik: " + chooser.getSelectedFile());

}else {

System.out.println("Nie wybrano pliku");

}}

Wyciągamy plik tylko jeśli użytkownik go wybrał

(a nie np. nacisnął X)

PlikiWyborFile.java

PlikiWyborPath.java

(60)

JFileChooser

Okienko pozwalające wybrać pik

public class JFileChooserExample {

public static void main(String[] args) { JFileChooser chooser = new JFileChooser();

chooser.setDialogTitle("Wybierz plik");

//Otwarcie okienka; metoda blokuje się do czasu wybrania pliku lub zamknięcia okna

int result = chooser.showDialog(null, "Wybierz");

if (JFileChooser.APPROVE_OPTION == result){

System.out.println("Wybrano plik: " +

chooser.getSelectedFile().toPath());

}else {

System.out.println("Nie wybrano pliku");

}}

}

PlikiWyborFile.java

PlikiWyborPath.java

(61)

Wczytywanie z pliku tekstowego

PlikiTekstoweOdczyt2.java

FileReader – łączymy strumień ze źródłem (plik.txt)

BufferedReader – buforujemy wczytywany plik

Wczytywanie linia po linii używając readLine

Zamknięcie strumienia

public class PlikiTekstoweOdczyt2 {

public static void main(String[] args) { FileReader fr = null;

String linia = "";

// OTWIERANIE PLIKU:

try {

fr = new FileReader("plik.txt");

BufferedReader bfr = new BufferedReader(fr);

// ODCZYT KOLEJNYCH LINII Z PLIKU:

while ((linia = bfr.readLine()) != null) { System.out.println(linia);

}

// ZAMYKANIE PLIKU fr.close();

} catch (Exception e) {

System.out.println("BLAD IO!");

System.exit(1);

(62)

Wczytywanie z pliku tekstowego

public class PlikiTekstoweOdczyt {

public static void main(String[] args) { FileReader fr = null;

String linia = "";

// OTWIERANIE PLIKU:

try {

fr = new FileReader("plik.txt");

} catch (FileNotFoundException e) {

System.out.println("BLAD PRZY OTWIERANIU PLIKU!");

System.exit(1);

}BufferedReader bfr = new BufferedReader(fr);

// ODCZYT KOLEJNYCH LINII Z PLIKU:

try {

while((linia = bfr.readLine()) != null){

System.out.println(linia);}

} catch (IOException e) {

System.out.println("BLAD ODCZYTU Z PLIKU!");

System.exit(2);

}

// ZAMYKANIE PLIKU

try {fr.close();} catch (IOException e) {

System.out.println("BLAD PRZY ZAMYKANIU PLIKU!");

System.exit(3);

}}

}

PlikiTekstoweOdczyt.java

Jeden wspólny blok try-catch można zastąpić kilkoma blokami szczegółowymi Otwarcie

Odczyt

Zamknięcie

(63)

public class PlikiTekstoweZapis {

public static void main(String[] args) {

String[] linie = { "Pierwsza linia tekstu do zapisania",

"druga linia - kilka liczb: (12), -23, 44.5, 2,5",

"trzecia linia " };

FileWriter fw = null;

try {

fw = new FileWriter("plik.txt");

BufferedWriter bw = new BufferedWriter(fw);

for (int i = 0; i < linie.length; i++) { bw.write(linie[i]);

bw.newLine();

}

bw.close();

} catch (IOException e) { e.printStackTrace();

} }

Zapisywanie do pliku tekstowego

PlikiTekstoweZapis.java

FileWriter – łączymy strumień z plikiem do zapisu (plik.txt)

BufferedReader – buforujemy zapisywany plik

Zapisujemy linia po linii używając write + newLine

Zamknięcie pliku

(zamykamy zewnętrzny strumień)

(64)

4 sposoby zapisu do pliku

FileWriter

Podstawowa klasa do zapisu plików tekstowych; używaj jeśli liczba zapisów w programie jest niewielka

BufferedWriter

Buforowanie umożliwia zmniejszenie ilości operacji IO; używaj jeśli spodziewasz się większej ilości zapisów do plików tekstowych

OutputStream

Zapisuje dane w postaci bajtów a nie znaków; nie poradzi sobie z bardziej zaawansowanym znakami Unicode, ale można używać do zapisu zwykłego tekstu ASCII; używaj jeśli potrzebujesz zapisać dane (niekoniecznie tekst)

BufferedOutputStream, jeśli mamy dużo zapisów bajtowych

Files.write

Metoda dodana w Java SE 7, wewnętrznie wykorzystuje OutputStream

WriteToFile4Ways.java

(65)

Random Access Files

Jeśli potrzebujesz coś zapisać w konkretnym miejscu istniejącego pliku

a nie tworzyć nowy lub dopisywać na końcu

należy wtedy użyć RandomAccessFile

pozwala na zapisanie na konkretnej pozycji w danym pliku

Pozycja jest określana przez offset, przesunięcie, w stosunku do początku pliku.

Uwaga, wtedy istniejący tekst zostanie NADPISANY

private static void writeToFile(String filePath, String data, int position) throws IOException {

RandomAccessFile file = new RandomAccessFile(filePath, "rw");

file.seek(position);

file.write(data.getBytes());

file.close();

}

RandomAccessFileOdczyt.java

(66)

Odczyt zasobów zawartych w JAR

To się przyda na projektach

– jeśli mamy plik, który jest wewnątrz pliku JAR, możemy go otworzyć za pomocą wywołania:

– Przykład odczytu:

InputStream inputStream = OdczytPlikuZJAR.class

.getResourceAsStream("rekopis.txt");

BufferedReader bufferedReader = new BufferedReader(

new InputStreamReader(inputStream, Charset.forName("UTF-8")));

String line = bufferedReader.readLine();

while (line != null) {

System.out.println(line);

line = bufferedReader.readLine();

}

getClass().getResourceAsStream("nazwa_pliku");

OdczytZPlikuJAR.java

(67)

Kodowanie

Czyli problemy z “krzaczkami”

(68)

Kodowanie

Z punktu widzenia informacji na dysku nie rozróżniamy plików

“znakowych” od “bajtowych”

Dla obu informacja jest zapisana za pomocą bajtów

W przypadku plików tekstowych należy bajty przetworzyć na znaki.

Sposób w jaki bajty są zamieniane na znaki nazywany jest kodowaniem.

Popularne rodzaje kodowania:

ASCII - pozwala zapisać znaki podstawowego alfabetu łacińskiego wykorzystując 1 bajt na zapis jednego znaku

CP1250 - pozwala zapisać znaki podstawowego alfabetu łacińskiego oraz pewne znaki diakrytyczne (w tym polskie) wykorzysując 1 bajt na zapis jednego znaku

UTF-8, UTF-16, UTF-32 - pozwala zapisać dowolne znaki, zużywając 1 (UTF-8), 2 (UTF-16) lub 4 (UTF-32) bajty na znak.

Najpopularniejsze jest UTF-8

Windows (języki środkowoeuropejskie) domyślnie używa CP-1250

Java używa kodowania UTF-16 jako wewnętrznej reprezentacji wszystkich

struktur, również string jest zbiorem znaków kodowanych w UTF-16.

(69)

Kodowanie

Najprostszą metodą na obsługę kodowania jest wczytanie

bajtów ze strumienia wejściowego i konwersja z odpowiednim kodowaniem przy użyciu konstruktora

new String(tablica_bajtów, "kodowanie").

By odczytać pliki tekstowe w jakimś kodowaniu należy uzyskać instancję klasy Charset.

Do uzyskania instancji klasy Charset służy metoda Charset.forName, przyjmująca nazwę danego kodowania:

Dodatkowo w Javie istnieje domyślne kodowanie możliwe do uzyskania za pomocą: Charset.defaultCharset().

Wczytanie pliku z wybranym kodowaniem:

InputStreamReader streamReader = new InputStreamReader(inputStream,

System.out.println("Kodowanie UTF-32: " + Charset.forName("UTF-32"));

System.out.println("Domyślne kodowanie w tym komputerze: " + Charset.defaultCharset());

(70)

Strumienie – przykładowe programy

Podstawy

BuforZnakowy.java – przykład użycia StringBuffer

Konsola.java – wczytanie i wypisanie tekstu w konsoli

Omawiane na wykładzie

FileDemo.java – używanie zmiennej File

PlikiTekstoweOdczyt(2).java - odczyt z plików tekstowych

PlikiTekstoweZapis.java – zapis do plików tekstowych

PlikiWyborFile.java, PlikiWyborPath.java – użycie JFileChooser

WriteToFile4Ways.java – cztery sposoby na zapisywanie do plików

RandomAccessFileOdczyt(Zapis).java – użycie RandomAccessFile

Inne

ListNotes.java – zapisywanie notatek do pliku tekstowego z konsoli

LoadObjects.java – zapisywanie obiektów klas (a nie tekstu / liczb)

SaveObjects.java – zapisywanie obiektów klas (a nie tekstu / liczb)

(71)

Więcej informacji

http://edu.pjwstk.edu.pl/wyklady/poj/scb/Strumienie/Strumienie.html

http://www.samouczekprogramisty.pl/strumienie-w-jezyku-java/

http://pojava.fizyka.pw.edu.pl/index.php/laboratoria/laboratorium-4

https://docs.oracle.com/javase/tutorial/essential/io/pathOps.html

(72)

Quiz time

(73)

Pytanie 1

Regularnie chcielibyśmy zapisywać do pliku wyniki symulacji. Plik ma format tekstowy. Którego strumienia

powinniśmy użyć do obsługi zapisu?

(a) InputStream (b) OutputStream (c) FileWriter

(d) BufferedWriter

(74)

Pytanie 1

Regularnie chcielibyśmy zapisywać do pliku wyniki symulacji. Plik ma format tekstowy. Którego strumienia

powinniśmy użyć do obsługi zapisu?

(a) InputStream (b) OutputStream (c) FileWriter

(d) BufferedWriter

(75)

Pytanie 2

Ile strumieni wyjściowych możemy mieć otwartych na raz?

(a) Zawsze tylko jeden na raz

(b) Jeden danego typu (1 wejściowy i 1 wyjściowy) (c) Wiele

(tyle, na ile pozwolą nam zasoby systemu)

(76)

Pytanie 2

Ile strumieni wyjściowych możemy mieć otwartych na raz?

(a) Zawsze tylko jeden na raz

(b) Jeden danego typu (1 wejściowy i 1 wyjściowy) (c) Wiele

(tyle, na ile pozwolą nam zasoby systemu)

(77)

Pytanie 3

Połącz domyślne kodowania do środowiska

(a) CP1250 (b) UTF-8 (c) UTF-16

(a) Linux (b) Java

(c) Windows

(78)

Pytanie 3

Połącz domyślne kodowania do środowiska

(a) CP1250 (b) UTF-8 (c) UTF-16

(a) Linux (b) Java

(c) Windows

(79)

Pytanie 4

Jeśli napisy w programie mi się brzydko krzaczą

– “panieĹ„skim rumieĹ„cem dziÄ™cielina”

jak najlepiej mogę zaradzić problemowi?

(a) Skasować wszystkie polskie znaki

(b) Sprawdzić, w jakim kodowaniu został zapisany problematyczny tekst i odpowiednio go

wczytywać

(c) Zmienić ustawienia w Javie by automatycznie

zawsze dobrze wczytywała wszystkie teksty

(80)

Pytanie 4

Jeśli napisy w programie mi się brzydko krzaczą

– “panieĹ„skim rumieĹ„cem dziÄ™cielina”

jak najlepiej mogę zaradzić problemowi?

(a) Skasować wszystkie polskie znaki

(b) Sprawdzić, w jakim kodowaniu został zapisany problematyczny tekst i odpowiednio go

wczytywać

(c) Zmienić ustawienia w Javie by automatycznie zawsze dobrze wczytywała wszystkie teksty

Cudów ni ma.

(81)

Prosta grafika w Javie

(82)

Dodawanie obrazów do projektu

Dodajemy obrazek do konkretnego pakietu

PPM na nazwie pakietu → 4 klasy strumieni abstrakcyjnych Import… File System → 4 klasy strumieni abstrakcyjnych → 4 klasy strumieni abstrakcyjnych

Browse.. Wybrać katalog → 4 klasy strumieni abstrakcyjnych → 4 klasy strumieni abstrakcyjnych Wybrać plik z listy Finish → 4 klasy strumieni abstrakcyjnych

Import…

1

2

3

4

5 – wybór z listy

6

(83)

Dodawanie obrazów do projektu

Dodajemy obrazek do konkretnego pakietu

PPM na nazwie pakietu → 4 klasy strumieni abstrakcyjnych Import… File System → 4 klasy strumieni abstrakcyjnych → 4 klasy strumieni abstrakcyjnych

Browse.. Wybrać katalog → 4 klasy strumieni abstrakcyjnych → 4 klasy strumieni abstrakcyjnych Wybrać plik z listy Finish → 4 klasy strumieni abstrakcyjnych

Import…

1

2

3

5 – wybór z 4 listy

nazwa_pakietu/nazwa_obrazka.JPG

(84)

Rysowanie obrazka na panelu

public class ImagePanel extends JPanel {

private BufferedImage image;

public ImagePanel() { super();

// Plik umieszczony w podpakiecie "obrazki"

URL resource = getClass().getResource("obrazki/zdjecie.JPG");

try {

image = ImageIO.read(resource);

} catch (IOException e) {

System.err.println("Blad odczytu obrazka");

e.printStackTrace();

}

Dimension dimension =

new Dimension(image.getWidth(), image.getHeight());

setPreferredSize(dimension);

}

public void paintComponent(Graphics g) { Graphics2D g2d = (Graphics2D) g;

g2d.drawImage(image, 0, 0, this);

} }

ImagePanel.java

(85)

Rysowanie obrazka na panelu

public class ImagePanel extends JPanel {

private BufferedImage image;

public ImagePanel() { super();

// Plik umieszczony w podpakiecie "obrazki"

URL resource = getClass().getResource("obrazki/zdjecie.JPG");

try {

image = ImageIO.read(resource);

} catch (IOException e) {

System.err.println("Blad odczytu obrazka");

e.printStackTrace();

}

Dimension dimension =

new Dimension(image.getWidth(), image.getHeight());

setPreferredSize(dimension);

}

public void paintComponent(Graphics g) { Graphics2D g2d = (Graphics2D) g;

g2d.drawImage(image, 0, 0, this);

}

ImagePanel.java

(86)

Programowanie Obiektowe (Wykład) Małgorzata Janik (WF PW)

Grafika

(87)

Grafika (Java2D)

Klasa Graphics2D – dużo większe możliwości tworzenia grafiki (m.in. łatwa obsługa przezroczystości, wypełnienia gradientowe, transformacje geometryczne, …)

• SimpleGraphics.java

– przykład wykorzystania klasy Graphics2d

• Gradient.java

– przykład wypełniania gradientowego

• TextureGraphics.java

– przykład wykorzystania tekstur

• SaveImage.java

– przykład tworzenia buforowanego obrazka i zapisu do

pliku graficznego.

(88)

Programowanie Obiektowe (Wykład) Małgorzata Janik (WF PW)

Przykład rysowania przy użyciu Graphics 2d

// Tworzenie ksztaltu i rysowanie wypelnienienia - fill Ellipse2D e=new Ellipse2D.Double(80,80,180,80);

g2.setPaint(Color.cyan);

g2.fill(e);

// Kontruktor Color() z czterema argumentami float // czwarty odpowiada za "przezroczystosc":

g2.setColor(new Color(1.0f, 1.0f, 0.0f, 0.6f));

g2.fill(star);

g2.setColor(new Color (0.2f, 0.2f, 0.2f, 0.5f));

g2.draw(star);

// Tworznie ksztaltu i rysownanie konturu - draw // set Stroke ustawia wlasciwosci linii

Rectangle2D r=new Rectangle2D.Double(50,50,100,200);

g2.setPaint(c0);

g2.setStroke(new BasicStroke(10));

g2.draw(r);

SimpleGraphics.java

(89)

Przykład wykorzystania tekstur przy użyciu Graphics 2d

// wykorzystanie tekstury do rysowania, tekstu itp. - setPaint()

TexturePaint tp = new TexturePaint(im, new Rectangle(imW,imH));

g2.setPaint(tp);

g2.fill(new RoundRectangle2D.Float(75,20,150,200,30,30));

g2.setFont(new Font("Verdana",Font.BOLD,24));

g2.drawString("Here's the text",10,260);

BufferedImage im =

new BufferedImage(imW,imH,

BufferedImage.TYPE_INT_RGB);

// nalezy wypełnić odpowiednim wzorem BufferedImage im, np.

Graphics2D g2im = im.createGraphics();

g2im.setColor(new Color(192,192,192));

g2im.fillRect(0,0,imW,imH);

//albo wczytać obrazek

TextureGraphics.java

(90)

Programowanie Obiektowe (Wykład) Małgorzata Janik (WF PW)

Przykład wykorzystania tekstur przy użyciu Graphics 2d

// wykorzystanie tekstury do rysowania, tekstu itp. - setPaint()

TexturePaint tp = new TexturePaint(im, new Rectangle(imW,imH));

g2.setPaint(tp);

g2.fill(new RoundRectangle2D.Float(75,20,150,200,30,30));

g2.setFont(new Font("Verdana",Font.BOLD,24));

g2.drawString("Here's the text",10,260);

BufferedImage im =

new BufferedImage(imW,imH,

BufferedImage.TYPE_INT_RGB);

// nalezy wypełnić odpowiednim wzorem BufferedImage im, np.

Graphics2D g2im = im.createGraphics();

g2im.setColor(new Color(192,192,192));

g2im.fillRect(0,0,imW,imH);

//albo wczytać obrazek

TextureGraphics.java

(91)

try {

ImageIO.write( im, "png" /* "png" "jpeg" ... format desired */, new File ( "gwiazda.png" ) /* target */ );

} catch (IOException e1) { e1.printStackTrace();

System.out.println("Blad przy zapisywaniu obrazku do pliku");

System.exit(1);

}

Zapisywanie obrazka do pliku

BufferedImage im;

// nalezy zadeklarować odpowiednio obrazek

SaveImage.java

(92)

Tworzenie i korzystanie z plików JAR

Biblioteka JFreeChart

(93)

Czym są pliki JAR?

JAR (ang. Java ARchive)

– archiwum ZIP używane do strukturalizacji i kompresji plików klas języka Java oraz

powiązanych z nimi zasobów i metadanych.

Archiwum JAR, o ile posiada

wyszczególnioną klasę główną, może

stanowić osobną aplikację

(94)

http://docs.oracle.com/javase/tutorial/deployment/jar/manifestindex.html

Archiwum JAR powinno zawierać plik manifestu umieszczony w ścieżce

– META-INF/MANIFEST.MF,

który informuje o sposobie użycia, przeznaczeniu archiwum, wskazuje klasę główną jeśli archiwum jest wykonywalne itp.

Większość współczesnych IDE dla Javy pozwala na szybkie tworzenie plików JAR i generowanie plików manifestu

Plik manifestu

(95)

Tworzenie pliku JAR w Eclipse – poprzez eksport projektu/projektów

Można tworzyć „zwykłe”

archiwum JAR, lub uruchamialne archiwum ze

wskazaniem klasy głównej

Cytaty

Powiązane dokumenty

Należy dołożyć opcje, w której oblicza się średnią dla dwóch osób i wyświetla obliczoną wartość w trybie konsolowym

● Definicja: paradygmat programowania opierający się na podziale kodu źródłowego programu na procedury i hierarchicznie ułożone bloki?. ● Rozwijał się w opozycji

CREATE TABLE table_name ( column1 datatype not null, column2 datatype,. column3 datatype,

Programowanie Obiektowe (Wykład) Małgorzata Janik (WF PW) 49/98. Odwołanie do Nadklasy

public void actionPerformed(ActionEvent arg0) {  setTitle(&#34;Anonimowa klasa wewnetrzna&#34;);  . } }

Programowanie Obiektowe (Wykład) Małgorzata Janik (WF PW) 80/116 public class MenuWindow extends JFrame {.

protected void done() - wywoływana po zakończeniu zadania, wykonywana w EDT, można w niej przeprowadzić „sprzątanie” i zaprezentować w GUI główny rezultat wykonywanego

– Ustalamy rodzaj bazy danych, w jakiej chcemy ją zapisać. Łatwe, → Łatwe, relacyjna... – Ustalamy jakiego DBMS będziemy używać.