Scanner

Scanner to jedna z najważniejszych klas w bibliotece standardowej języka Java, służąca do odczytu danych wprowadzanych przez użytkownika. Jest niezwykle użyteczna w wielu sytuacjach, od prostych programów, które wymagają interakcji z użytkownikiem, po bardziej zaawansowane aplikacje, które muszą przetwarzać dane z różnych źródeł. W tym artykule szczegółowo omówimy klasę Scanner oraz jej zastosowania, funkcje i najlepsze praktyki związane z jej używaniem.

Czym jest klasa Scanner?

Klasa Scanner należy do pakietu java.util i jest wykorzystywana do skanowania danych wejściowych. Umożliwia odczyt danych z różnych źródeł, takich jak:

  • standardowe wejście (np. klawiatura),
  • pliki,
  • strumienie tekstowe,
  • łańcuchy znaków.

Scanner jest idealnym rozwiązaniem, gdy potrzebujemy wprowadzić dane w formie tekstu, liczby, czy innych typów danych, a następnie je przetworzyć w naszym programie. Jego główną zaletą jest prostota i elastyczność. Umożliwia on wygodne pobieranie różnych typów danych, jak liczby całkowite (int), zmiennoprzecinkowe (double), teksty (String) i inne.

Jak używać klasy Scanner?

Aby używać klasy Scanner, należy ją zaimportować na początku programu:

import java.util.Scanner;

Następnie tworzymy obiekt klasy Scanner, który będzie odpowiadał za odczyt danych wejściowych. Najczęściej używamy jej do odczytu danych z konsoli. Przykład prostego programu, który odczytuje dane wejściowe od użytkownika:

import java.util.Scanner; public class Main {     public static void main(String[] args) {         Scanner scanner = new Scanner(System.in); // Tworzymy obiekt Scanner do odczytu z konsoli                  System.out.print("Podaj swoje imię: ");         String name = scanner.nextLine(); // Odczytujemy linię tekstu                  System.out.println("Witaj, " + name + "!");                  scanner.close(); // Zamykamy scanner, kiedy już nie będzie potrzebny     } }

W tym przykładzie program prosi użytkownika o podanie imienia, które jest następnie odczytywane przy pomocy metody nextLine(). Scanner w tym przypadku odczytuje dane z wejścia standardowego (klawiatury).

Najczęściej używane metody klasy Scanner

Scanner posiada wiele metod, które pozwalają na odczyt różnych typów danych. Oto niektóre z najczęściej używanych metod:

1. nextLine()

Metoda ta odczytuje całą linię tekstu, aż do napotkania znaku nowej linii.

String input = scanner.nextLine();

2. next()

Metoda ta odczytuje pojedynczy token (słowo) oddzielony białymi znakami (np. spacjami, tabulatorami, nowymi liniami). Jest używana, gdy chcemy odczytać jedno słowo.

String word = scanner.next();

3. nextInt()

Służy do odczytu liczb całkowitych.

int number = scanner.nextInt();

4. nextDouble()

Służy do odczytu liczb zmiennoprzecinkowych (double).

double pi = scanner.nextDouble();

5. hasNext()

Sprawdza, czy w strumieniu wejściowym znajduje się kolejny token.

if (scanner.hasNext()) {     String nextInput = scanner.next(); }

6. hasNextInt() i inne metody hasNextX()

Metody te sprawdzają, czy kolejne dane wejściowe mogą być przekonwertowane na dany typ. Na przykład, hasNextInt() sprawdza, czy następny token to liczba całkowita.

if (scanner.hasNextInt()) {     int number = scanner.nextInt(); }

7. close()

Metoda close() zamyka obiekt Scanner i zwalnia zasoby. Należy ją wywołać, kiedy skończymy pracować z obiektem Scanner.

scanner.close();

Odczyt danych z różnych źródeł

Chociaż najczęściej używamy Scanner do odczytu danych z konsoli, może on także czytać dane z innych źródeł, takich jak pliki czy strumienie.

Odczyt z pliku

Scanner może być używany do odczytu danych z pliku. W tym przypadku należy przekazać obiekt typu File lub InputStream do konstruktora Scanner.

import java.util.Scanner; import java.io.File; import java.io.IOException; public class FileReader {     public static void main(String[] args) throws IOException {         File file = new File("example.txt");         Scanner scanner = new Scanner(file); // Tworzymy Scanner, który odczytuje dane z pliku                  while (scanner.hasNextLine()) {             String line = scanner.nextLine(); // Odczytujemy każdą linię pliku             System.out.println(line);         }                  scanner.close(); // Zamykamy scanner po zakończeniu odczytu     } }

Odczyt z ciągu znaków

Scanner może także odczytywać dane z łańcucha znaków (String), co jest przydatne, gdy musimy analizować dane wejściowe już przechowywane w zmiennej typu String.

String input = "100 200 300"; Scanner scanner = new Scanner(input); while (scanner.hasNextInt()) {     System.out.println(scanner.nextInt()); } scanner.close();

Błędy związane z używaniem klasy Scanner

Chociaż klasa Scanner jest bardzo wygodna, może prowadzić do kilku typowych problemów. Oto niektóre z nich:

  1. Problemy z odczytem liczby po wczytaniu tekstu: Kiedy używamy metod takich jak nextInt(), a potem próbujemy wczytać linię tekstu przy pomocy nextLine(), może wystąpić problem z przechwyceniem nowej linii. To zjawisko wynika z tego, że nextInt() nie konsumuje nowej linii po odczycie liczby, przez co metoda nextLine() może od razu zwrócić pustą linię. Można to rozwiązać przez dodanie dodatkowego wywołania nextLine() po odczycie liczby.
int number = scanner.nextInt(); scanner.nextLine(); // Konsumujemy nową linię po odczycie liczby String text = scanner.nextLine(); // Teraz możemy poprawnie odczytać tekst
  1. Zamknięcie Scanner po odczycie z System.in: Kiedy używamy Scanner do odczytu z wejścia standardowego (System.in), zamknięcie tego obiektu może spowodować zamknięcie całego strumienia wejściowego, co utrudni kolejne operacje odczytu z konsoli w tym samym programie. W takich przypadkach zaleca się zamykanie Scanner tylko wówczas, gdy naprawdę kończymy pracę z programem.

Najlepsze praktyki

  1. Unikaj zamykania Scanner przy używaniu System.in: Jak wspomniano, nie zamykaj obiektu Scanner do odczytu z konsoli w przypadkach, gdy będziesz potrzebować ponownie korzystać z wejścia w tym samym programie. Zamknięcie Scanner na System.in może skutkować błędami podczas dalszego korzystania z wejścia.
  2. Obsługuje wyjątki: Choć większość metod Scanner nie rzuca wyjątków w przypadku złych danych (np. próba wczytania liczby tam, gdzie oczekiwany jest tekst), warto obsługiwać wyjątki, szczególnie przy pracy z plikami. Może to zapobiec awariom programu i umożliwić wygodne zarządzanie błędami.
  3. Zawsze zamykaj Scanner po zakończeniu pracy: Chociaż nie należy zamykać Scanner używanego do odczytu z konsoli, zawsze pamiętaj, aby zamknąć go po zakończeniu pracy z plikami lub innymi zasobami, co pozwala zwolnić używane zasoby.
  4. Bądź świadomy różnic między metodami nextLine() a next(): nextLine() odczytuje całą linię, natomiast next() zwraca tylko pierwszy token (słowo) w linii. Warto wybrać odpowiednią metodę w zależności od potrzeb.

Podsumowanie

Klasa Scanner jest niezwykle przydatnym narzędziem w języku Java, które umożliwia łatwy dostęp do danych wejściowych. Dzięki różnym metodom pozwala na odczyt danych z różnych źródeł i przetwarzanie ich w sposób bardzo elastyczny. Znajomość metod klasy Scanner, takich jak next(), nextLine(), nextInt() czy hasNext(), jest kluczowa dla każdego programisty Java, zwłaszcza w kontekście aplikacji wymagających interakcji z użytkownikiem lub analizy danych wejściowych.