Java Scanner类完全指南:用法、实例与常见问题解析
Java中的Scanner类
Java的Scanner类是java.util包的一部分。它在Java 1.5版本中被引入。Scanner主要用于接收用户输入并将其解析为基本数据类型,如int、double或默认字符串。它是一个使用正则表达式生成标记来解析数据的实用工具类。
Java Scanner类的构造函数
如果查看Scanner类,会发现它有很多构造函数。

大多数构造函数都使用以下三种对象之一:
- InputStream – 最常见的方式是将System.in作为参数传入以接收用户输入。
- File或Path – 我们也可以扫描文件数据并处理文件中的值。
- String – 我们也可以为字符串来源创建扫描器,并解析其中的值。
如果查看第二个参数,它是用于指定字符集的,当你不想使用默认字符集进行解析时可以使用。
Scanner类的重要方法
让我们来看一下最常用的Scanner类方法:
- useDelimiter(String pattern) – 设置扫描器使用的分隔符。默认分隔符是空白字符。
- hasNext() – 如果输入中还有另一个标记,则返回true。这是一个阻塞方法,它会持续等待用户输入。
- next() – 从扫描器返回下一个标记。它与hasNext()方法一起使用。
- close() – 扫描器占用资源较多,因此使用完毕后,应使用此方法关闭它并释放系统资源。
还有许多实用方法可以检查和直接解析输入标记为int、short、long、byte、BigDecimal等类型的值。
初始化和使用扫描器的步骤
- 第一步是通过使用适当的构造函数初始化扫描器类,根据输入类型选择InputStream、File或String。如果需要,设置分隔符和字符集。
- 第二步是使用hasNext()方法等待输入的标记。
- 然后使用next()方法读取标记并逐个处理它们。
扫描器是如何工作的?
- Scanner类使用指定的分隔符模式将其输入分解为标记。
- next()方法用于逐个读取标记并处理它们。
- 最后,关闭Scanner实例以释放系统资源。
扫描器示例
让我们来看一下Scanner类的一些常见用法和示例代码片段。
1. 读取用户输入
这是Scanner类最常见的用法。我们可以通过使用System.in作为输入源来实例化并读取用户输入。
// read user input
Scanner sc = new Scanner(System.in);
System.out.println("Please enter your name");
String name = sc.next();
System.out.println("Hello " + name);
sc.close();
输出:
Please enter your name
Pankaj
Hello Pankaj
嗯,看起来简单且运行良好。然而,上述代码存在一个问题。在阅读下一部分之前,你能否检查代码并尝试找出问题所在?
让我们看看当我在输入框中写下我的全名时会发生什么。
Please enter your name
Pankaj Kumar
Hello Pankaj
现在你一定明白了,这是因为空格是分隔符。扫描器将输入分成两个令牌 – Pankaj和Kumar。但是,我们只调用了一次next()方法,所以只打印了“Hello Pankaj”。
我们该如何解决这个问题?
很简单。我们可以使用 useDelimiter() 方法将分隔符更改为换行符。
Scanner sc = new Scanner(System.in);
sc.useDelimiter(System.getProperty("line.separator"));
System.out.println("Please enter your name");
String name = sc.next();
System.out.println("Hello " + name);
sc.close();
使用扫描器解析文件数据。
这是文章《Java中的Scanner类》的第3部分(共3部分)。
让我们看一个简单的例子,使用Scanner类来读取和解析CSV文件。假设我有一个名为employees.csv的文件,内容如下。
1,Jane Doe,CEO
2,Mary Ann,CTO
3,John Lee,CFO
让我们在我们的Java程序中读取文件并获取一个员工列表。
package com.Olivia.java;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class ScannerExamples {
public static void main(String[] args) throws IOException {
// create scanner for the CSV file
Scanner sc = new Scanner(new File("employees.csv"));
// set delimiter as new line to read one line as a single token
sc.useDelimiter(System.getProperty("line.separator"));
// create the List of Employees
List<Employee> emps = new ArrayList<>();
while (sc.hasNext()) {
Employee emp = parseEmployeeData(sc.next());
emps.add(emp);
}
// close the scanner
sc.close();
// print employee records
System.out.println(emps);
}
private static Employee parseEmployeeData(String record) {
// create scanner for the String record
Scanner sc = new Scanner(record);
// set delimiter as comma
sc.useDelimiter(",");
Employee emp = new Employee();
emp.setId(sc.nextInt());
emp.setName(sc.next());
emp.setRole(sc.next());
// close the scanner
sc.close();
return emp;
}
}
class Employee {
private int id;
private String name;
private String role;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
@Override
public String toString() {
return "Emp[" + id + "," + name + "," + role + "]";
}
}
- 第一步是为CSV文件创建扫描器,并将换行符设置为分隔符。
- 然后,对于包含CSV格式员工记录的每一行,使用另一个扫描器和逗号作为分隔符进行解析。parseEmployeeData()方法正在解析每一行并创建Employee对象。
- 最后,我们将员工对象添加到列表中并打印出来。
输出:[员工[1, 简朵, 首席执行官], 员工[2, 玛丽安, 首席技术官], 员工[3, 约翰李, 首席财务官]]
3. Java 正则表达式的 Scanner 示例
假设我们有一个字符串source,我们想要处理其中的整数。我们可以使用带有非数字正则表达式的扫描器,以获取只有整数作为处理对象的标记。
//using regex to read only integers from a string source
String data = "1a2b345c67d8,9#10";
Scanner sc1 = new Scanner(data);
// setting non-digit regex as delimiter
sc1.useDelimiter("\\D");
while(sc1.hasNext()) {
System.out.println(sc1.next());
}
// don't forget to close the scanner
sc1.close();
输出:
1
2
345
67
8
9
10
结论
Java Scanner是一个用于读取用户输入或处理基于正则表达式的文件或字符串源的实用类。然而,在实际应用中,最好使用CSV解析器来解析CSV数据,而不是使用Scanner类以获得更好的性能。
参考:API文档,Java中的正则表达式