
本文介绍使用 Java 的 Scanner.findAll() 与正则表达式,根据姓名、年龄、性别三字段精确匹配文件中连续的多行结构化数据,并提取对应成绩,避免多 Scanner 同步错位问题。
本文介绍使用 java 的 `scanner.findall()` 与正则表达式,根据姓名、年龄、性别三字段精确匹配文件中连续的多行结构化数据,并提取对应成绩,避免多 scanner 同步错位问题。
在处理结构化文本日志(如学生测试记录)时,常见的错误是为每个字段创建独立的 Scanner 实例——这会导致各扫描器读取位置完全脱节,无法保证“姓名→年龄→性别→成绩”四行在文件中物理连续且顺序严格对应。正确做法是单次遍历 + 正则模式匹配,将目标条件编译为一个跨行正则表达式,交由 Scanner.findAll() 原生支持的流式匹配能力高效定位。
以下是一个健壮、简洁的实现方案:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.util.regex.MatchResult;
import java.util.regex.Pattern;
public class StudentResultFinder {
public static void main(String[] args) throws FileNotFoundException {
Scanner userInput = new Scanner(System.in);
System.out.println("请输入学生全名:");
String stuName = userInput.nextLine().trim();
System.out.println("请输入学生年龄:");
int stuAge = userInput.nextInt();
userInput.nextLine(); // 消费换行符,避免 nextLine() 被跳过
System.out.println("请输入学生性别(Female/Male):");
String stuGender = userInput.nextLine().trim();
// 构建跨行匹配模式:姓名
年龄
性别
成绩(如 97.0%、100%、85.5%)
String scorePattern = "\d+(?:\.\d+)?%";
String fullPattern = Pattern.quote(stuName) + "
" +
Integer.toString(stuAge) + "
" +
Pattern.quote(stuGender) + "
" +
scorePattern;
Scanner fileScanner = new Scanner(new File("Example.txt"));
Pattern pattern = Pattern.compile(fullPattern);
fileScanner.findAll(pattern)
.map(MatchResult::group)
.findFirst()
.ifPresentOrElse(
result -> {
String[] lines = result.split("
");
String score = lines.length > 3 ? lines[3] : "N/A";
System.out.println("✅ 找到匹配学生:" + stuName);
System.out.println(" 年龄:" + stuAge + ",性别:" + stuGender);
System.out.println(" 成绩:" + score);
},
() -> System.out.println("❌ 未找到完全匹配的学生记录")
);
fileScanner.close();
userInput.close();
}
}关键要点说明:
- ✅
Pattern.quote()防注入:对用户输入的stuName和stuGender使用Pattern.quote()包裹,防止姓名含正则元字符(如.、*、()导致意外匹配失败或安全风险; - ✅
显式换行匹配:文件中每条记录严格按「姓名→换行→年龄→换行→性别→换行→成绩」排列,正则中的确保行间关系精确; - ✅ 成绩正则鲁棒性:
\d+(?:\.\d+)?%支持整数百分比(93%)、一位小数(97.0%)、多位小数(84.32%),(?:...)是非捕获分组,提升性能; - ⚠️ 资源必须关闭:
fileScanner.close()和userInput.close()不可省略,尤其在生产环境中防止文件句柄泄漏; - ⚠️ 无异常吞并:示例保留了
throws FileNotFoundException,实际项目中建议用 try-with-resources 或try-catch包裹并提供友好提示(如“成绩文件不存在,请检查路径”)。
? 进阶建议:若需支持大小写不敏感搜索(如
"female"也匹配"Female"),可在编译Pattern时添加Pattern.CASE_INSENSITIVE标志;若记录间存在空行,可将替换为\s* \s*以容忍空白符。
该方案摒弃了易出错的手动逐行状态管理,转而利用正则引擎的声明式匹配能力,逻辑清晰、可维护性强,是处理固定格式多行文本检索的推荐实践。

















