1. Общ преглед
Класът Scanner е удобен инструмент, който може да анализира примитивни типове и низове с помощта на регулярни изрази и е въведен в пакета java.util в Java 5.
В този кратък урок ще говорим за неговите методи hasNext () и hasNextLine () . Въпреки че тези два метода може да изглеждат доста сходни в началото, те всъщност правят доста различни проверки.
Можете също така да прочетете повече за универсалния клас скенери в краткото ръководство тук.
2. hasNext ()
2.1. Основна употреба
Методът hasNext () проверява дали скенерът има друг маркер във входа си. A Scanner разбива своя принос в жетони с помощта на модел разделител, който съвпада с празно пространство по подразбиране. Тоест hasNext () проверява входните данни и връща true, ако има друг небел интервал.
Трябва също да отбележим няколко подробности относно разделителя по подразбиране:
- Пробелът включва не само интервалния знак, но и интервала на табулацията ( \ t ), подаването на редове ( \ n ) и дори повече символи
- Непрекъснатите интервали се третират като единичен разделител
- Празните редове в края на входа не се отпечатват - т.е. hasNext () връща false за празни редове
Нека да разгледаме пример за това как hasNext () работи с разделителя по подразбиране. Първо ще подготвим входен низ, който да ни помогне да проучим резултата от синтактичния анализ на S canner :
String INPUT = new StringBuilder() .append("magic\tproject\n") .append(" database: oracle\n") .append("dependencies:\n") .append("spring:foo:bar\n") .append("\n") // Note that the input ends with a blank line .toString();
След това нека анализираме входа и отпечатаме резултата:
Scanner scanner = new Scanner(INPUT); while (scanner.hasNext()) { log.info(scanner.next()); } log.info("--------OUTPUT--END---------")
Ако стартираме горния код, ще видим изхода на конзолата:
[DEMO]magic [DEMO]project [DEMO]database: [DEMO]oracle [DEMO]dependencies: [DEMO]spring:foo:bar [DEMO]--------OUTPUT--END---------
2.2. С потребителски разделител
Досега разгледахме hasNext () с разделителя по подразбиране. Най- Scanner клас осигурява useDelimiter (String образец) метод , който ни позволява да промените разделител. След като разделителят бъде променен, методът hasNext () ще извърши проверката с новия разделител вместо този по подразбиране.
Нека видим друг пример за това как hasNext () и next () работят с персонализиран разделител. Ще използваме повторно входа от последния пример.
След скенера анализира знак съвпадение низ "на зависимости: ", ние ще се промени разделител за двоеточие ( :) , така че да може да анализира и да извлича всяка стойност на зависимостите:
while (scanner.hasNext()) { String token = scanner.next(); if ("dependencies:".equals(token)) { scanner.useDelimiter(":"); } log.info(token); } log.info("--------OUTPUT--END---------");
Нека да видим получения резултат:
[DEMO]magic [DEMO]project [DEMO]database: [DEMO]oracle [DEMO]dependencies: [DEMO] spring [DEMO]foo [DEMO]bar [DEMO]--------OUTPUT--END---------
Страхотен! Успешно извличаме стойностите в „ зависимости “, но има някои неочаквани проблеми с прекъсването на редове . Ще видим как да ги избегнем в следващия раздел.
2.3. С регулярно изражение като разделител
Нека да прегледаме резултата в последния раздел. Първо, забелязахме, че има прекъсване на ред ( \ n ) преди „ пролетта “. Променихме разделителя на „ : “ след извличането на маркера „зависимости:“ . Прекъсването на реда след „ зависимостите: “ сега става част от следващия маркер. Следователно hasNext () връща true и прекъсването на реда е отпечатано.
По същата причина подаването на редове след „ хибернация “ и последния празен ред стават част от последния маркер, така че два празни реда се отпечатват заедно с „ хибернация “.
Ако можем да направим едно и също двоеточие и интервал като разделител, тогава стойностите на „зависимости“ ще бъдат правилно анализирани и проблемът ни ще бъде решен. За да постигнем това, нека променим повикването useDelimiter (“:”) :
scanner.useDelimiter(":|\\s+");
„ : | \\ s + “ тук е регулярен израз, съответстващ на единичен „:“ или един или повече пробели. С тази корекция изходът се превръща в:
[DEMO]magic [DEMO]project [DEMO]database: [DEMO]oracle [DEMO]dependencies: [DEMO]spring [DEMO]foo [DEMO]bar [DEMO]--------OUTPUT--END---------
3. hasNextLine ()
Методът hasNextLine () проверява дали има друг ред във входа на обекта Scanner , без значение дали редът е празен или не.
Нека вземем същия вход отново. Този път ще добавим номера на редове пред всеки ред във входа, използвайки методите hasNextLine () и nextLine () :
int i = 0; while (scanner.hasNextLine()) log.info(String.format("%d log.info("--------OUTPUT--END---------");
Сега, нека да разгледаме нашите резултати:
[DEMO]1|magic project [DEMO]2| database: oracle [DEMO]3|dependencies: [DEMO]4|spring:foo:bar [DEMO]5| [DEMO]--------OUTPUT--END---------
Както очаквахме, номерата на редовете се отпечатват и последният празен ред също е там.
4. Заключение
В тази статия, ние научихме, че Scanner е hasNextLine () проверки метод, ако има друг ред във входа, без значение дали линията е празен или не, докато hasNext () използва разделител за да проверите за друг знак.
Както винаги, пълният изходен код за примерите е достъпен в GitHub.