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