Java Scanner 类是 java.util 包的一部分。它是在 Java 1.5 版本中引入的。Scanner 主要用于接收用户输入并将它们解析为原始数据类型,例如 int、double 或 default String。它是一个实用程序类,通过生成令牌使用正则表达式解析数据。
Java 扫描器类构造函数
如果您查看 Scanner 类,就会发现有很多构造函数。
大多数构造函数都使用以下三个对象之一:
- InputStream – 我们通过 System.in 来接收用户输入的最常见的地方。
- 文件或路径——我们也可以扫描文件数据并使用文件中的值。
- 字符串——我们也可以为字符串源创建一个扫描器并从中解析值。
如果你看第二个参数,如果你不想使用默认字符集进行解析,它是指定一个字符集。
Scanner类的重要方法
让我们看看一些最常用的 Scanner 类方法。
- useDelimiter(String pattern) – 用于扫描仪的分隔符。默认分隔符是空格。
- hasNext() – 如果输入中有另一个标记,则返回 true。这是一种阻塞方法,它会一直等待用户输入。
- next() – 从扫描器返回下一个标记。它与 hasNext() 方法结合使用。
- close() – 扫描器是资源繁重的,所以一旦你完成它,使用这个方法关闭它并释放系统资源。
有许多实用方法可以检查和直接解析 int、short、long、byte、BigDecimal 等中的输入标记。
初始化和使用Scanner 的步骤
- 第一步是根据输入类型(例如 InputStream、File 或 String)使用适当的构造函数来初始化扫描器类。如果需要,请设置要使用的分隔符和字符集。
- 第二步是使用 hasNext() 方法等待输入令牌。
- 然后使用next()方法读取token并一一处理。
Scanner 如何工作?
- Scanner 类使用指定的分隔符模式将其输入分解为标记。
- next() 方法用于逐个读取令牌并对其进行处理。
- 最后,关闭 Scanner 实例以释放系统资源。
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();
2. 使用 Scanner 解析文件数据
让我们看一个使用扫描器类读取和解析 CSV 文件的简单示例。比方说,我有一个包含以下内容的雇员.csv 文件。
1,Jane Doe,CEO``2,Mary Ann,CTO``3,John Lee,CFO
让我们阅读该文件并获取 Java 程序中的员工列表。
package com.journaldev.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对象。
- 最后,我们将员工对象添加到列表中并打印出来。
输出:[Emp[1,Jane Doe,CEO], Emp[2,Mary Ann,CTO], Emp[3,John Lee,CFO]]
3. Java Scanner 正则表达式示例
假设我们有一个字符串源,我们只想处理其中存在的整数。我们可以使用带有非数字正则表达式的扫描器来仅获取整数作为标记来处理它们。
//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 类以获得更好的性能。