CodeGym /Java 博客 /China /Scanner 类
作者
Milan Vucic
Programming Tutor at Codementor.io

Scanner 类

已在 China 群组中发布
你好! 我们今天的课程会很特别! 在以前,完成任务和编写程序的过程很简单:我们编写一些代码,运行 main() 方法,程序做要做的事情,就行了。 但现在一切都将改变。今天我们将学习如何切实与程序互动:我们将教它如何对我们的操作做出反应! 在我们开始分析代码之前,你有没有处理过像扫描仪这样的设备?可能处理过。扫描仪的内部非常复杂,但其工作原理非常简单:读取用户提供的数据(如护照或保单),并将这些信息存储在内存中(例如,以图像的方式)。 今天,我们会创建自己的扫描仪。当然,它不能处理纸质文件,但处理文本不成问题 :) 让我们开始吧!

Java 的 Scanner 类

首先,我们必须熟悉 java.util.Scanner 类。它的功能非常简单。与真正的扫描仪一样,它从你指定的来源读取数据。例如字符串、文件和控制台。接下来,它识别信息并进行相应的处理。下面是最简单的示例:

public class Main {

   public static void main(String[] args) {

       Scanner scanner = new Scanner("It matters not how strait the gate,\n" +
               "How charged with punishments the scroll,\n" +
               "I am the master of my fate,\n" +
               "I am the captain of my soul");
       String s = scanner.nextLine();
       System.out.println(s);
   }
}
我们已经创建了一个扫描仪对象,并指定了它的数据源(文本字符串)。nextLine() 方法访问数据源(即含四行诗的文本),找到下一个未读的行(在本例中是第一行),再将其返回。然后在控制台上显示出来:控制台输出:

It matters not how strait the gate,
我们可以多次使用 nextLine() 方法并显示整个诗的摘录:

public class Main {

   public static void main(String[] args) {

       Scanner scanner = new Scanner("It matters not how strait the gate,\n" +
               "How charged with punishments the scroll,\n" +
               "I am the master of my fate,\n" +
               "I am the captain of my soul");
       String s = scanner.nextLine();
       System.out.println(s);
       s = scanner.nextLine();
       System.out.println(s);
       s = scanner.nextLine();
       System.out.println(s);
       s = scanner.nextLine();
       System.out.println(s);
   }
}
我们的扫描仪每次前进一步,读取下一行。该程序的输出显示如下:

It matters not how strait the gate, 
How charged with punishments the scroll, 
I am the master of my fate, 
I am the captain of my soul
正如我们已经说过的,扫描仪的数据源不一定是字符串。例如,数据源可能是控制台。好消息是,以前,我们只显示数据,但现在将从键盘上读取数据!看看 Scanner 类还做了什么:

public class Main {

   public static void main(String[] args) {

       Scanner sc = new Scanner(System.in);
       System.out.println("Enter a number:");

       int number = sc.nextInt();

       System.out.println("Thanks! You entered the number " + number);

   }
}
nextInt() 方法读取并返回输入的数字。在程序中,我们使用该方法将值赋给变量 number。现在它更像一个真实的扫描仪了!程序会请求用户输入任何数字。在用户输完后,程序感谢用户,显示结果,然后结束。但仍存在严重问题。用户可能错误输入了内容。下面是当前程序停止工作的一个例子:

public class Main {

   public static void main(String[] args) {

       Scanner sc = new Scanner(System.in);
       System.out.println("Enter a number:");

       int number = sc.nextInt();

       System.out.println("Thanks! You entered the number " + number);

   }
}
现在尝试输入字符串“CodeGym”而不是数字:控制台输出:

Enter a number: 
CodeGym 
Exception in thread "main" java.util.InputMismatchException 
at java.util.Scanner.throwFor(Scanner.java:864) 
at java.util.Scanner.next(Scanner.java:1485) 
at java.util.Scanner.nextInt(Scanner.java:2117) 
at java.util.Scanner.nextInt(Scanner.java:2076) 
at Main.main(Main.java:10) Process finished with exit code 1
Scanner 类 - 1糟糕。我们有大麻烦了-_-为了避免这种情况,我们需要想出一种方法来验证用户输入的数据。例如,如果用户输入的不是数字,那么最好显示一个警告,说明输入的信息不是数字。如果信息没问题,就可以确认。但这需要我们“展望未来”,看看信息流会显示什么。Scanner 可以实现此功能吗?如何实现!可以采用许多方法来实现此功能:hasNextInt() — 该方法会检查下一个输入数据块是否是数字(根据需要返回 true 或 false)。hasNextLine() — 该方法会检查下一个输入块是否是字符串。hasNextByte(), hasNextShort()hasNextLong()hasNextFloat()hasNextDouble() — 所有这些方法都对其余的数据类型执行类似的检查。现在试试改变数字读取程序:

public class Main {

   public static void main(String[] args) {

       Scanner sc = new Scanner(System.in);
       System.out.println("Enter a number:");

       if (sc.hasNextInt()) {
           int number = sc.nextInt();
           System.out.println("Thanks! You entered the number " + number);
       } else {
           System.out.println("Sorry, but this is clearly not a number. Restart the program and try again!");
       }

   }
}
现在我程序检查下一个输入的字符是否是数字。并且仅当它是数字时才显示确认。如果输入没有通过检查,程序会记录下来并要求用户再试一次。 基本上,你可以与 Scanner 对象通信,提前了解需要输入的数据类型。数字、字符串或其他?数字?什么类型?intshortlong? 这种灵活性使你有机会构建依赖于用户行为的程序逻辑。我们应该注意另一个重要的方法:useDelimiter()。 你将字符串传入此方法。该字符串包含要用作分隔符的字符。 例如,假设我们突然对日本诗歌感兴趣,并决定使用扫描仪读取大诗人松尾芭蕉写的一些俳句。 即使三段不同的诗歌是以一个很难看的字符串形式传递的,我们仍可以轻松拆分并优美呈现出来:

public class Main {
   public static void main(String[] args) {
       Scanner scan = new Scanner("On a withered branch'" +
               "A crow has alighted.'" +
               "Nightfall in autumn." +
               "''***''" +
               "Such a moon above,'" +
               "Like a tree cut at the root:'" +
               "he fresh cut is white." +
               "''***''" +
               "How the river floods!'" +
               "A heron wanders on short legs,'" +
               "Knee-deep in the water.");

       scan.useDelimiter("'");

       while (scan.hasNext()) {
           System.out.println(scan.next());
       }

       scan.close();
   }
}
我们使用 "\n/*/*/*"(新行字符和三个星号)作为分隔符。最后,我们得到漂亮的控制台输出,就像在书中一样:
On a withered branch 
A crow has alighted. 
Nightfall in autumn. 

*** 

Such a moon above, 
Like a tree cut at the root: 
The fresh cut is white. 

*** 

How the river floods! 
A heron wanders on short legs, 
Knee-deep in the water.
此示例还有一个方法必须提出来:close()。像任何处理 I/O 流的对象一样,扫描仪在完成后必须关闭,这样它就不会消耗计算机的资源。绝不要忘记使用 close() 方法!

public class Main {

   public static void main(String[] args) {

       Scanner sc = new Scanner(System.in);
       System.out.println("Enter a number:");

       int number = sc.nextInt();

       System.out.println("Thanks! You entered the number " + number);
      
       sc.close(); // Now we've done everything right!

   }
}
今天就讲到这里!正如你所见,Scanner 类很有用,可轻松使用!:)
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION