Obsługa błędów, Wejście/Wyjście

Transkrypt

Obsługa błędów, Wejście/Wyjście
2016-04-28
Języki Programowania II
Wykład 6
Obsługa błędów, Strumienie
Przypomnienie
• Typy podstawowe, klasy
• Pakiety
• Modyfikatory dostępu
– Działają dla klas, a nie obiektów
• Inicjalizacja
– Konstruktory i kolejność inicjalizacji
– Odśmiecanie pamięci i samodzielne zwalnianie innych zasobów
• Przeciążanie metod/konstruktorów
• Kapsułkowanie
• Uogólnienie/uszczegółowienie
– Polimorfizm
– Wzorce projektowe: Adapter, Fabryka, Singleton
– Interfejsy, klasy abstrakcyjne
Obsługa błędów
1
2016-04-28
Sytuacje wyjątkowe
•
•
•
•
Nie da się ich do końca wyeliminować
– Kończy się miejsce na dysku (bo zajął je inny proces)
– Podczas przesyłania danych zrywa się połączenie sieciowe
– Inni niepoprawnie używają naszych bibliotek
Przekazują wartość null lub za krótką tablicę
Gdzie podjąć działania naprawcze?
– Zazwyczaj nie w miejscu wykrycia sytuacji wyjątkowej
– Przerywamy normalny przebieg programu i przekazujemy informacje o
błędzie „na zewnątrz”
Sposoby obsługi
– Historycznie specjalny wynik oznaczający błąd lub ustawianie globalnie
dostępnej flagi
– Jak zmusić programistów żeby „nie zapomnieli” sprawdzić
– Obecnie zgłaszanie wyjątku, który przerywa normalny tryb wykonania
programu i rozwija stos wywołań aż będzie obsłużony lub program się
zakończy błędem
Przykład
Wynik
•
•
Poziom szczegółowości zależy od ustawień kompilatora
– Domyślnie ślad stosu wywołań oraz numery linii kodu
– Kiedy to nam nie odpowiada?
Informacje o błędach są wypisywane na standardowe wyjście błędu, więc
mogą się poprzeplatać
2
2016-04-28
Nadzór obsługi wyjątków przez kompilator
• Kompilator nie pozwoli przegapić wyjątków
• Można zadeklarować więcej wyjątków na przyszłość
• Czy tak jest rzeczywiście lepiej?
– W Javie jest też druga możliwość
Obsługa wyjątku
• Wybierany jest zawsze pierwszy pasujący blok
• Pozostałe bloki są pomijane
• Wyjątki które nie pasują do żadnej klauzuli dalej rozwijają stos
Przykład
3
2016-04-28
Wynik
• Tym razem program nie został przerwany
• Informacje o wyjątku wypisaliśmy sami
Hierarchia wyjątków
•
•
•
•
W pakiecie java.lang
Na Error aplikacja nic nie poradzi (mogą się pojawić wszędzie)
Na Exception powinna być przygotowana (kontrolowane)
RuntimeException to błąd programisty można obsługiwać, ale
lepiej zadbać żeby się nie pojawiły (niekontrolowane)
Przykład
4
2016-04-28
Zgłaszanie wyjątku w bloku catch
• Wyjątki zgłaszane w bloku catch nie są obsługiwane przez tą
samą instrukcję try-catch
• Przydatne jak w danym kontekście nie ma możliwości
obsłużenia
• Ponowne zgłoszenie nie zmienia zapamiętanego śladu stosu
Blok finally
• Do instrukcji try można dodać blok finally, który jest
wykonywany niezależnie od tego jak try się kończy
• Można też użyć samego finally i nie obsługiwać żadnych
wyjątków
Kolejność finally
• Jeśli w try nie wystąpił wyjątek to blok finally wykonywany
jest bezpośrednio po jego zakończeniu
• Jeśli w try wystąpił wyjątek, ale żaden catch nie pasuje lub
żadnego nie ma, to blok finally wykonywany jest
bezpośrednio po wystąpieniu wyjątku, ale przed rozwijaniem
stosu
• Jeśli w try wystąpił wyjątek i jest pasujący catch, to blok
finally wykonywany jest bezpośrednio po zakończeniu obsługi
wyjątku
– nawet jak w trakcie obsługi wystąpił kolejny wyjątek
5
2016-04-28
Przykład
Wynik
Strumienie
6
2016-04-28
Przykład wejścia w Javie
System wejścia/wyjścia
• Czemu to musi być rozległe
– Dane mogą pochodzić z różnych mediów: konsola, pliki, połączenia
sieciowe, …
– Różne sposoby obsługi: sekwencyjnie, ze swobodnym dostępem,
buforowanie, znakowo/binarnie, znak po znaku/linia po linii, ...
– Czasami konieczne dodatkowe przetwarzanie: liczenie sumy kontrolnej,
kompresja, szyfrowanie, …
• Wzorzec Dekorator
– Przykład: okienko z suwakiem
• Strumienie (ang. stream)
– InputStream, OutputStream, Reader, Writer
– Znakowe od Javy 1.1
– Znakowe nie zastępują binarnych
– Łatwa konwersja z binarnych na znakowe (przydatna np. przy kompresji)
Przykład konwersji
7
2016-04-28
Strumienie
• Standardowe strumienie są dla: plików, tablic bajtów/znaków, obiektów
String, łączach (ang. pipe)
• Wiele innych obiektów pozwala otrzymać strumień: Socket, URL
• File{Input,Output}Stream i File{Reader,Writer} –
pozwalają odczytywać i zapisywać pliki dyskowe
– Nazwa pliku lub obiekt File jako parametr konstruktora
– Dla obiektów wyjściowych drugi parametr wskazuje czy dopisywać na końcu
• ByteArray{Input,Output}Stream i
CharArray{Reader,Writer} – bufor w pamięci oparty na tablicy
odpowiednio bajtów lub znaków
– Dla ob. wejściowego przekazujemy tablicę
– Dla ob. wyjściowego początkowy rozmiar bufora
Strumienie cd.
• StringBufferInputStream (nie ma odpowiednika do zapisu i jest
deprecated)
• String{Reader,Writer} – bufor w pamięci oparty na napisie String
(implementacja posługuje się obiektem StringBuffer)
– Dla ob. wejściowego przekazujemy napis
– Dla ob. wyjściowego początkowy rozmiar bufora
• Piped{Input,Output}Stream i Piped{Reader,Writer} – łącze
do komunikacji między procesami
– Najpierw tworzymy obiekt jedne rodzaju (konstr. bezparametrowy)
– Potem przekazujemy konstruktorowi obiektu drugiego rodzaju
– Strumienie zostają połączone łączem
Podstawowe operacje na danych
• read() – następny bajt/znak lub -1 jak koniec strumienia
• read(byte[]) lub read(char[]) – odczytuje dane do tablicy, zwraca
liczbę odczytanych porcji (chyba że już koniec wtedy -1), blokuje się dopóki nie
napotka końca
• read(byte[], int, int) lub read(char[], int, int) –
analogicznie wypełnia podtablicę
• write(byte) lub write(char) – zapisuje jedną porcję danych
• Analogiczne wersje dla tablic i tablic z przedziałami
• Wersja znakowa może zapisywać napisy i ich wycinki
• Strumienie trzeba zamykać close()
8
2016-04-28
Kodowanie znaków
• W Javie znaki są wewnętrznie kodowane w Unicode 16bit
• Użycie bezparametrowych konstruktorów
{Input,Output}StreamWriter skutkuje konwersją do dla domyślnego
kodowania danej platformy
– oba konstruktory są przeciążone i można jawnie wskazać kodowanie
• Również File{Reader,Writer} stosują domyślne kodowanie
– to tylko opakowanie na {Input,Output}StreamWriter
Wzorzec Dekorator
Przykłady Dekoratorów
• Buffered{Input,Outpu}Stream i Buffered{Reader,Writer}
– Dodaje buforowanie (istotne dla efektywności)
– Do natychmiastowego opróżnienia bufora służy flush()
– Zazwyczaj bufor jest opróżniany również przy close()
• PrintStream i PrintWriter
– Dodatkowe metody wypisujące dane w sposób czytelny dla człowieka w dwóch wersjach
print() i println()
– Dla wygody klasy posiadają dodatkowe konstruktory, które zwalniają z konieczności otwierania
samemu strumienia do pisania na pliku i dekorowania go buforowaniem
– Zalecana jest PrintWriter, gdyż zapisuje końce linii w sposób przyjęty na danej platformie
– Uwaga: metody nie przepuszczają IOException, trzeba używać metody checkError()
• PushBackInputStream i PushBackReader
– Dodają metodę unread()pozwalającą odesłać z powrotem ostatnio odczytane dane
– Odesłane dane są zapamiętywane w buforze. Kolejne odczyty najpierw pobierają dane z bufora,
a dopiero jak jest pusty ze strumienia
– Przydaje się podczas budowy kompilatora.
9
2016-04-28
Przykłady Dekoratorów c.d.
• LineNumberInputStream i LineNumberReader
– Dodają metodę getLineNumber(), która zwraca liczbę odczytanych do
tej pory linii
– LineNumberInputStream jest oznaczona jako deprecated
• Data{Input,Output}Stream (brak odpowiedników znakowych)
– Dodają nowe metod do przesyłania przez strumień wartości typów
podstawowych oraz napisów w sposób niezależny od platformy
• Object{Input,Output}Stream (brak odpowiedników znakowych)
– Dodają nowe metody pozwalające przesyłać przez strumień obiekty
implementujące interfejs java.io.Serializable
Przykłady Dekoratorów c.d.
• Checked{Input,Output}Stream (brak odpowiednika znakowego)
– Wylicza sumę kontrolną dla danych przesyłanych przez strumien
– Należą do pakietu java.util.zip
• GZIP{Input,Output}Stream (brak odpowiedników znakowych)
– Dane przesyłane przez strumień są kompresowane przy pomocy prostego
algorytmu GZIP.
– Należą do pakietu java.util.zip
• Zip{Input,Output}Stream (brak odpowiedników znakowych)
– Dane przesyłane przez strumień są kompresowane przy pomocy algorytmu
Zip
– Należą do pakietu java.util.zip
• Cipher{Input,Output}Stream (brak odpowiedników znakowych)
– Dane przesyłane przez strumień są szyfrowane lub deszyfrowane przy
pomocy obiektu Cipher
– Należą do pakietu java.crypto
Standardowe we/wy
• Standardowe wejście
– System.in
– InputStream
– BufferedReader stin = new BufferedReader(new
InputStreamReader(System.in));
– Scanner in = new Scanner(System.in);
• Standardowe wyjście
– System.out
– PrintStream
•
Standardowe wyjście błędu
– System.oerr
– PrintStream
• Programy można łączyć w potoki
• Przekierowanie
– setOut(PrintStream), setIn(InputStream) i setErr(PrintStream)
10
2016-04-28
Przykład kompresja
Przykład kompresja ZIP
Co dalej….?
W poniedziałek - wykład z Java Swing.
Na następne zajęcia :
• Lista 3 – wybór i dokumentacja projektu UML
• Ćwiczenia – przegląd projektów
11

Podobne dokumenty