Java Scanner: kontrola unosa sa konzole, može i da skenira fajlove
Java klasa Scanner je alatka koja olakšava skeniranje korisničkog unosa sa konzole; iako može i da skenira sadržaj fajlova, mi obično više volimo da je koristimo u ovoj prvoj ulozi, jer se skeniranje fajlova može obaviti preko tokova fajlova.
U nastavku ćemo kroz nekoliko jednostavnih primera objasniti klasu Scanner.
01. Skeniranje unosa sa konzole
Obično koristimo klasu Scanner da skeniramo unos sa konzole, posebno za one koji tek uče Javu, to je prilično kul, jer konačno možemo da dohvatimo podatke koje sami želimo da unesemo.
Pogledajmo sledeći primer:
Scanner scanner = new Scanner(System.in); // kreiranje Scanner objekta, čitanje podataka iz standardnog ulaznog toka
System.out.print("Unesite ceo broj: ");
int num = scanner.nextInt(); // dohvatanje celog broja koji je uneo korisnik
System.out.println("Uneli ste ceo broj: " + num);
scanner.nextLine(); // čitanje znaka za novi red, da se ne bi uticalo na sledeće čitanje
System.out.print("Unesite string: ");
String str = scanner.nextLine(); // dohvatanje stringa koji je uneo korisnik
System.out.println("Uneli ste string: " + str);
scanner.close(); // zatvaranje Scanner objektaNakon pokretanja možete komunicirati preko konzole, za početnike će to verovatno biti prilično zanimljivo.

Među tim, System.in vraća ulazni tok bajtova InputStream, što tačno odgovara System.out.

1) nextLine
Metoda nextLine() skenira znakove u ulaznom toku sve dok ne naiđe na znak za novi red \n na kraju reda, a zatim vraća sadržaj tog reda kao string; istovremeno, nextLine() pomera poziciju Scanner objekta na početak sledećeg reda, tako da sledeće čitanje podataka kreće od početka sledećeg reda.
Scanner scanner = new Scanner(System.in); // kreiranje Scanner objekta, čitanje podataka iz standardnog ulaznog toka
System.out.println("Unesite više redova teksta, prazan red za kraj: ");
StringBuilder sb = new StringBuilder(); // kreiranje StringBuilder objekta za čuvanje pročitanog teksta
String line = scanner.nextLine(); // čitanje prvog reda iz ulaznog toka
while (!line.isEmpty()) { // ako pročitani red nije prazan, čitamo sledeći red
sb.append(line).append("\n"); // dodavanje sadržaja trenutnog reda u StringBuilder objekat, sa prelomom
line = scanner.nextLine(); // čitanje sledećeg reda
}
System.out.println("Uneli ste tekst:\n" + sb.toString()); // ispis pročitanog teksta
scanner.close(); // zatvaranje Scanner objekta2) nextInt
nextInt() služi da iz ulaznog toka pročita sledeći celi broj i vrati ga; ako u ulaznom toku nema celog broja, ili unos nije celi broj, biće bačen izuzetak InputMismatchException.

3) Druge metode
Pored ove dve često korišćene metode, u klasi Scanner ima i nekih drugih metoda:
boolean hasNext(): proverava da li u ulaznom toku ima sledećeg tokena.boolean hasNextLine(): proverava da li u ulaznom toku ima sledećeg reda.String next(): čita sledeći token iz ulaznog toka (koristi podrazumevani separator, obično razmak ili znak za novi red).double nextDouble(): čita sledeći broj dvostruke tačnosti iz ulaznog toka.
Ajmo jedan demo.
Scanner scanner = new Scanner(System.in); // kreiranje Scanner objekta, čitanje podataka iz standardnog ulaznog toka
System.out.print("Unesite ceo broj: ");
if (scanner.hasNextInt()) { // provera da li u ulaznom toku ima sledećeg celog broja
int num = scanner.nextInt(); // čitanje sledećeg celog broja iz ulaznog toka
System.out.println("Uneli ste ceo broj: " + num);
} else {
System.out.println("Unos nije ceo broj!");
}
scanner.nextLine(); // čitanje znaka za novi red iz ulaznog toka
System.out.print("Unesite više reči razdvojenih razmacima: ");
while (scanner.hasNext()) { // provera da li u ulaznom toku ima sledećeg tokena
String word = scanner.next(); // čitanje sledeće reči iz ulaznog toka
System.out.println("Uneli ste reč: " + word);
}
scanner.nextLine(); // čitanje znaka za novi red iz ulaznog toka
System.out.print("Unesite realan broj: ");
if (scanner.hasNextDouble()) { // provera da li u ulaznom toku ima sledećeg realnog broja
double num = scanner.nextDouble(); // čitanje sledećeg realnog broja iz ulaznog toka
System.out.println("Uneli ste realan broj: " + num);
} else {
System.out.println("Unos nije realan broj!");
}
scanner.nextLine(); // čitanje znaka za novi red iz ulaznog toka
System.out.print("Unesite string: ");
if (scanner.hasNextLine()) { // provera da li u ulaznom toku ima sledećeg reda
String line = scanner.nextLine(); // čitanje sledećeg reda iz ulaznog toka
System.out.println("Uneli ste string: " + line);
} else {
System.out.println("Unos nije string!");
}
scanner.close(); // zatvaranje Scanner objekta02. Skeniranje fajlova
Naravno, Scanner se može koristiti i za skeniranje fajlova, način je takođe veoma jednostavan, evo primera koda:
try {
// kreiranje File objekta koji predstavlja fajl za skeniranje
File file = new File("docs/instalacija-okruzenja.md");
Scanner scanner = new Scanner(file); // kreiranje Scanner objekta, čitanje podataka iz fajla
while (scanner.hasNextLine()) { // provera da li u fajlu ima sledećeg reda
String line = scanner.nextLine(); // čitanje sledećeg reda iz fajla
System.out.println(line); // ispis pročitanog reda
}
scanner.close(); // zatvaranje Scanner objekta
} catch (FileNotFoundException e) {
System.out.println("Fajl ne postoji!");
}U gornjem primeru smo prvo kreirali File objekat koji predstavlja fajl koji želimo da skeniramo. Zatim smo konstruktorom klase Scanner kreirali Scanner objekat, prosledivši fajl kao parametar konstruktoru. U while petlji koristimo metodu hasNextLine() da proverimo ima li u fajlu sledećeg reda, i ako ima, metodom nextLine() čitamo taj red kao string, a metodom println() ga ispisujemo. Na kraju, pre završetka programa, metodom close() zatvaramo Scanner objekat.
Pored korišćenja petlje i nextLine, možemo i metodom useDelimiter da postavimo oznaku kraja fajla \Z kako bismo pročitali ceo fajl.
// kreiranje File objekta koji predstavlja fajl za skeniranje
Scanner scanner = new Scanner(new File("docs/instalacija-okruzenja.md")); // kreiranje Scanner objekta, čitanje podataka iz fajla
scanner.useDelimiter("\\Z"); // postavljanje separatora na kraj fajla
if (scanner.hasNext()) { // provera da li u fajlu ima sledećeg reda
String content = scanner.next(); // čitanje sledećeg reda iz fajla
System.out.println(content); // ispis pročitanog reda
}
scanner.close(); // zatvaranje Scanner objektaU regularnim izrazima \Z označava kraj ulaza, odnosno oznaku kraja fajla. U klasi Scanner možemo koristiti \Z kao separator kako bismo pročitali ceo sadržaj fajla.
03. Traženje podudaranja
Pored pomenutog skeniranja ulaznog toka konzole i fajlova, Scanner pruža još četiri metode koje počinju sa find za traženje podudaranja:

Pogledajmo primer:
String input = "good good study, day day up.";
Scanner scanner = new Scanner(input);
String result;
// korišćenje metode findInLine() za traženje reči u stringu
result = scanner.findInLine("study");
System.out.println("findInLine(): " + result); // izlaz "study"
// korišćenje metode findWithinHorizon() za traženje reči u stringu
scanner = new Scanner(input);
result = scanner.findWithinHorizon("study", 20);
System.out.println("findWithinHorizon(): " + result); // izlaz "study"
scanner.close(); // zatvaranje Scanner objektaU gornjem primeru smo prvo kreirali string input koji predstavlja tekst u kom tražimo. Zatim smo konstruktorom klase Scanner kreirali Scanner objekat i prosledili mu input kao ulazni tok. Potom smo metodama findInLine() i findWithinHorizon() tražili reč „study“ u stringu. Metoda findInLine() traži podudaranja u trenutnom redu, dok findWithinHorizon() traži podudaranja u zadatom ograničenom opsegu. U ovom primeru smo opseg pretrage ograničili na prvih 20 znakova.
Treba napomenuti da i findInLine() i findWithinHorizon() vraćaju pronađeno podudaranje. Ako podudaranje nije pronađeno, vraćaju null. Pored toga, findInLine() i findWithinHorizon() ignorišu podrazumevani separator, pa je za zadavanje obrasca pretrage potrebno koristiti regularne izraze. U ovom primeru smo kao obrazac pretrage koristili string „study“.
Naravno, možemo koristiti i regularne izraze, na primer da u sledećem fajlu pronađemo ključnu reč openjdk.

Kôd može da izgleda ovako:
// kreiranje File objekta koji predstavlja fajl za skeniranje
Scanner scanner = new Scanner(new File("docs/instalacija-okruzenja.md")); // kreiranje Scanner objekta, čitanje podataka iz fajla
Pattern pattern = Pattern.compile("op..jdk");
String result;
while ((result = scanner.findWithinHorizon(pattern, 0)) != null) {
System.out.println("findWithinHorizon(): " + result);
}Regularnim izrazom pattern predstavljamo ključnu reč openjdk, pri čemu . u op..jdk označava bilo koji znak — možete pogledati članak o regularnim izrazima za više detalja.
Zatim u while petlji tražimo sva pojavljivanja openjdk u fajlu; ako je drugi parametar metode findWithinHorizon 0, to znači da se ignoriše granica, a ako se ništa ne pronađe, vraća se null.

Pošto u fajlu ima dve ključne reči openjdk, izlaz izgleda ovako:

04. Kratak osvrt
Ukratko, klasa Scanner je moćna alatka za obradu ulaza, ne samo da može da skenira ulazni tok konzole, već i fajlove, i pruža više metoda za čitanje različitih tipova podataka, kao što su next(), nextInt(), nextLine(), nextDouble() itd.
Pored toga, separator se može postaviti metodom useDelimiter(), a podudaranja se mogu tražiti preko findInLine(), findWithinHorizon() itd.
