Operacje wejścia i wyjścia w Javie
Dotychczas wszystkie nasze programy były oparte o dane, które były wpisane w kod. Ostatnio zobaczyliśmy jak pobierać argumenty w konsoli. Jednak jest to zbyt mało elastyczna metoda, aby mogła zaspokoić wszystkie potrzeby.
Nadszedł czas, aby poznać podstawowe metody pobierania danych od użytkownika w wierszu poleceń i wyświetlaniu ich odpowiednio sformatowanych. W tym celu musimy poznać klasę Scanner
.
W przyszłości pokażemy jak tworzyć takie elementy w GUI (ang. Graphic user interface), ale na razie musimy poznać wiele innych technik nim przejdziemy do podstaw grafiki w Javie.
Klasa Scanner
Za pobieranie danych wejściowych w oknie konsoli odpowiada obiekt klasy Scanner
. Do pobierania danych służą metody – do każdego typu należy użyć jednej z nich.
Konstruktory klasy Scanner
Poniżej kawałek dokumentacji z dostępnymi metodami i konstruktorami.
Scanner(InputStream source)
– tworzy obiekt klasy Scanner ze strumienia wejścia.Scanner(File source)
– tworzy obiekt, który pobiera dane ze wskazanego pliku.Scanner(Path source)
– jak wyżej.
Jak widać można utworzyć też obiekt, który będzie pobierał dane z pliku. Jednakże szczegółowo obsługą plików zajmiemy się w dalszych częściach kursu.
Metody klasy Scanner
- String
nextLine()
– wczytuje kolejny wiersz danych. - String
next()
– wczytuje kolejne słowo do znaku spacji. - byte
nextByte()
– wczytuje bajt. - short
nextShort()
– wczytuje liczbę typu short. - int
nextInt()
– wczytuje liczbę typu int. - long
nextLong()
– wczytuje liczbę typu long. - double
nextDouble()
– wczytuje liczbę typu double. - float
nextFloat()
– wczytuje liczbę typu float.
To są najważniejsze metody klasy Scanner
. W przypadku potrzeby użycia innych metod można sprawdzić aktualną dokumentację.
Import i użycie
Aby można było skorzystać z klasy Scanner
należy zaimportować ją z pakietu java.util.
1 |
import java.util.Scanner; |
Poniżej pokażemy przykład pobrania danych od użytkownika a następnie wyświetlimy je na ekranie.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import java.util.Scanner; class Main { public static void main(String[] args) { Scanner scan = new Scanner(System.in); System.out.println("Jak masz na imię?"); String imie = scan.nextLine(); System.out.println("Podaj ulubioną liczbę"); int liczba = scan.nextInt(); System.out.println("Nazywasz się " + imie + ", a twoją ulubioną liczbą jest " + liczba); } } |
Błędne dane wejściowe
W każdym programie należy powszechnie stosować zasadę, aby nie ufać użytkownikowi przy wprowadzaniu danych wejściowych. Na początku naszego szkolenia wspominaliśmy, że Java jest językiem o ścisłej kontroli typów, a więc każda zmienna może przechowywać tylko jeden rodzaj danych.
W listingu, który znajduje się powyżej mieliśmy do podania dwa typy danych – String
do reprezentacji imienia oraz int
do przechowywania wieku użytkownika. Typ String
jest bardziej odporny na różne błędy, gdyż zarówno liczby, litery oraz białe znaki mogą być przez niego przechowywane. Inaczej sytuacja wygląda z typem int
, który jest typem prostym przechowującym liczby całkowite.
Przykładowy poprawny przebieg programu wygląda następująco.
1 2 3 4 5 |
Jak masz na imię? Kamil Podaj ulubioną liczbę całkowitą 6 Nazywasz się Kamil, a twoją ulubioną liczbą jest 6 |
Przy założeniu, że użytkownik zawsze wpisze poprawne dane wejściowe program zachowuje się w porządku. Co jednak, gdy pomyli się, albo celowo wpisze coś innego niż jest oczekiwane przez program? Rozpatrzmy inny przebieg programu.
1 2 3 4 5 6 7 8 9 10 |
Jak masz na imię? K4mi7 Podaj ulubioną liczbę całkowitą 6.0 Exception in thread "main" java.util.InputMismatchException at java.base/java.util.Scanner.throwFor(Scanner.java:939) at java.base/java.util.Scanner.next(Scanner.java:1594) at java.base/java.util.Scanner.nextInt(Scanner.java:2258) at java.base/java.util.Scanner.nextInt(Scanner.java:2212) at MyClass.main(MyClass.java:10) |
Wyjątek InputMismatchException
Jak widać na powyższym przykładzie do obiektu typu String
można wpisać nawet zmieszane wartości liter i cyfr, jednakże gdy próbowaliśmy pobrać typ double
metodą nextInt()
kompilator wyrzucił wyjątek InputMismatchException
. Następnie działanie programu zostało przerwane i dalsza część kodu nie została wykonana.
Wyjątki są ważnym elementem Javy. Na tym etapie jedynie sygnalizujemy ich istnienie, natomiast zainteresowanych odsyłamy do artykułu poświęconemu wyjątkom oraz ich obsłudze.
Wyjątek InputMismatchException
należy do grupy wyjątków typu unchecked, co oznacza, że odpowiednia konstrukcja kodu może im zapobiec. W tym wypadku pomoże nam instrukcja warunkowa if oraz metoda hasNextInt()
.
1 2 3 4 |
int liczba = 0; if(scan.hasNextInt()){ liczba = scan.nextInt(); } |
Po wykonaniu tego sprawdzenia na pewno już nie zaskoczy nas żaden błąd użytkownika.
Wyświetlanie i formatowanie danych
Do wyświetlania danych służy dobrze już nam znany obiekt System.out, który posiada kilka wariantów metod. Każda z nich potrafi wydrukować dane różnych typów.
print()
– drukuje na ekranie podany ciąg lub zmienną liczbową, którą wcześniej konwertuje do typu String.println()
– drukuje na ekranie podany ciąg lub zmienną liczbową, którą wcześniej konwertuje do typu String. Na końcu dodaje znak nowego wiersza.printf(String format, Object... args)
– Metoda, która drukuje i formatuje dane.
Jeśli zwyczajnie chcemy pokazać wynik dzielenia liczb zmiennoprzecinkowych, to program standardowo pokaże jak najdokładniejsze przybliżenie (w zależności od typu zmiennej). Jednakże do niektórych zastosowań potrzebujemy dokładnie 2 miejsc po przecinku lub chcemy pokazywać znak przed liczbą. Znaki konwersji powinny być dobrze znane programistom znającym język C. Sama składnia prinf()
jest identyczna.
1 2 |
System.out.printf("%5.2f", 10.0d / 3.0d); //pokaże 2 miejsca po przecinku, a cała liczba zajmie 5 miejsc czyli jedną spację, cyfrę 3, kropkę i 2 cyfry z zaokrąglenia. |
Warto zauważyć, że pomiędzy cudzysłowami ciąg to po prostu łańcuch znakowy w związku z tym można tam wpisać dowolny tekst i użyć operatorów konwersji.
1 |
System.out.printf("wynik = %5.2f", 10.0d / 3.0d); |
Operatory konwersji printf
d – liczba całkowita dziesiętna
e – liczba zmiennoprzecinkowa w notacji wykładniczej
f – liczba zmiennoprzecinkowa
x – liczba całkowita w szesnastkowym systemie liczbowym (heksadecymalnym)
o – liczba całkowita w ósemkowym systemie liczbowym (oktalnym)
s – łańcuch znaków
c – znak
b – wartość logiczna
+ – znak przed każdą wartością
– wyrównanie do lewej (gdy pole jest większe niż liczba cyfr do wyświetlenia)
0 – wypełnienie zerami po lewej stronie
( – ujęcie ujemnych liczb w nawiasie
# – w przypadku liczb zmiennoprzecinkowych dodawany jest przecinek (nawet w przypadku braku wartości ułamkowej) lub dodanie przedrostka przed liczbą szesnastkową lub ósemkową.
W następnej części szkolenia wrócimy do programowania obiektowego – dziedziczenia.