
Lớp Scanner trong Java là một phần của gói java.util. Nó được giới thiệu từ phiên bản Java 1.5. Scanner chủ yếu được dùng để nhận input từ người dùng và phân tích chúng thành các kiểu dữ liệu nguyên thủy như int, double hoặc String mặc định.
Đây là một utility class hỗ trợ phân tích dữ liệu bằng cách sử dụng regular expressions để tạo ra các tokens.
Các Constructors của Java Scanner Class
Nếu bạn xem trong Scanner class, bạn sẽ thấy có rất nhiều constructors.

Hầu hết các constructors của Scanner đều sử dụng một trong ba đối tượng sau:
- InputStream – trường hợp phổ biến nhất, nơi ta truyền vào System.in để nhận input từ người dùng.
- File hoặc Path – cho phép scan dữ liệu từ file và làm việc với các giá trị trong file đó.
- String – ta cũng có thể tạo một scanner từ một chuỗi nguồn (string source) và parse các giá trị từ đó.
Nếu bạn để ý đến tham số thứ hai, nó được dùng để chỉ định character set trong trường hợp bạn không muốn dùng character set mặc định khi parse.
Các phương thức quan trọng của Scanner Class
Dưới đây là một số phương thức thường được sử dụng nhất của Scanner class:
- useDelimiter(String pattern) – xác định delimiter mà scanner sẽ sử dụng. Mặc định, delimiter là khoảng trắng.
- hasNext() – trả về true nếu còn token khác trong input. Đây là một blocking method, nghĩa là nó sẽ chờ cho đến khi có input từ người dùng.
- next() – trả về token kế tiếp từ scanner. Thường được dùng kết hợp với hasNext().
- close() – Scanner tiêu tốn nhiều tài nguyên hệ thống, vì vậy sau khi sử dụng xong, nên gọi phương thức này để đóng scanner và giải phóng tài nguyên.
Ngoài ra, Scanner còn có nhiều utility methods để kiểm tra và parse trực tiếp input token sang các kiểu dữ liệu như int, short, long, byte, BigDecimal, v.v.
Các bước khởi tạo và sử dụng Scanner
- Bước đầu tiên là khởi tạo Scanner class bằng constructor phù hợp dựa trên loại input như InputStream, File hoặc String. Nếu cần, thiết lập delimiter và character set để sử dụng.
- Bước tiếp theo là chờ input token bằng phương thức hasNext().
- Sau đó dùng phương thức next() để đọc token và xử lý từng cái một.
Scanner hoạt động như thế nào?
- Scanner class chia input thành các tokens dựa trên delimiter pattern đã chỉ định.
- Các phương thức next() được dùng để đọc từng token một và xử lý chúng.
- Cuối cùng, đóng Scanner instance để giải phóng tài nguyên hệ thống.
Ví dụ về Scanner
1. Đọc input từ người dùng
Đây là cách sử dụng phổ biến nhất của Scanner class. Chúng ta có thể khởi tạo Scanner với System.in làm input source và đọc dữ liệu người dùng nhập vào.
// 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();
Kết quả xuất ra:
Please enter your name
Pankaj
Hello Pankaj
Đoạn code trên trông có vẻ đơn giản và hoạt động tốt nhưng lại có một vấn đề. Không đọc phần tiếp theo, bạn có thể xem lại code và thử tìm ra lỗi không?
Hãy cùng xem điều gì xảy ra khi tôi nhập đầy đủ họ tên của mình vào input.
Please enter your name
Pankaj Kumar
Hello Pankaj
Giờ thì bạn chắc hẳn đã nhận ra rồi: vấn đề xảy ra là vì whitespace được dùng làm delimiter. Scanner đã tách input thành hai tokens – Pankaj và Kumar. Nhưng chúng ta chỉ gọi phương thức next() một lần, nên chỉ in ra “Hello Pankaj”.
Làm sao để khắc phục?
Rất đơn giản. Chúng ta có thể đổi delimiter thành ký tự newline character bằng cách sử dụng phương thức 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. Phân tích dữ liệu từ File bằng Scanner
Hãy cùng xem một ví dụ đơn giản để đọc và parse file CSV bằng Scanner class. Giả sử tôi có một file employees.csv với nội dung như sau:
1,Jane Doe,CEO
2,Mary Ann,CTO
3,John Lee,CFO
Hãy đọc file đó và lấy danh sách Employees trong chương trình Java của chúng ta.
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 + "]";
}
}
• Bước đầu tiên là tạo scanner cho file CSV và thiết lập newline làm delimiter.
• Sau đó, với mỗi dòng chứa bản ghi nhân viên ở định dạng CSV, parse nó bằng một scanner khác và dùng comma làm delimiter. Hàm parseEmployeeData() sẽ parse từng dòng và tạo ra một đối tượng Employee.
• Cuối cùng, chúng ta thêm đối tượng employee vào danh sách và in nó ra.
Output: [Emp[1,Jane Doe,CEO], Emp[2,Mary Ann,CTO], Emp[3,John Lee,CFO]]
3. Ví dụ về Java Scanner với Regular Expression
Giả sử chúng ta có một string source và muốn xử lý chỉ các integers có trong đó. Chúng ta có thể sử dụng scanner với non-digit regex để chỉ lấy các integers làm tokens và xử lý chúng.
//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();
Kết quả xuất ra:
1
2
345
67
8
9
10
Kết luận
Lớp Scanner trong Java là một utility class được dùng để đọc dữ liệu nhập từ người dùng hoặc xử lý việc phân tích cú pháp đơn giản dựa trên regex từ file hoặc chuỗi. Tuy nhiên, trong các ứng dụng thực tế, việc sử dụng CSV parsers để phân tích dữ liệu CSV sẽ hiệu quả hơn so với dùng Scanner class, vì mang lại hiệu suất tốt hơn.