You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java读取txt学生名册实现姓名ID互查及异常处理问题咨询

现有实现的问题

你的当前代码可以跑通基础场景,但存在不少边界隐患和不符合开发规范的点:

  • 匹配逻辑不可靠:使用line.contains()做模糊匹配会出现子串误匹配问题,比如搜索Rea会错误命中Reagan的记录;用replace做内容截取也有风险,要是ID中刚好包含「姓名+空格」的子串,会导致返回结果错误,同时如果分隔符是多个空格、制表符,替换逻辑会直接失效。
  • Scanner资源不可复用:文件对应的Scanner游标是单向的,遍历一次后就走到了文件末尾,如果你后续要做多次查询,第二次调用查询方法会直接抛异常,扩展性为0。
  • 异常使用不规范:方法签名直接抛出Exception基类属于不好的实践,过于宽泛的异常声明会让调用方无法预判具体故障类型,你可以自定义业务异常,或者直接用JDK内置的NoSuchElementException这类更明确的异常类型。
  • 资源泄漏风险:你把文件流的close()方法放在了try块内部,如果查询过程中抛出异常,close()不会被执行,会一直占用文件句柄造成资源泄漏。
  • 代码冗余:findID和findName两个方法的逻辑几乎完全一致,只是查询的目标字段不同,重复代码不利于后续维护。

优化方案

最核心的优化点是预加载全量数据到内存映射表,不用每次查询都遍历文件,同时解决上面的所有问题:

  1. 程序启动时一次性读取全量名册数据,分别存入HashMap<String, String>类型的nameToId和idToName两个映射表,后续查询直接走O(1)的哈希表查询,性能远高于每次遍历文件。
  2. 每行数据用split("\\s+", 2)按空白字符分割成两部分,严格区分姓名和ID,避免模糊匹配的问题。
  3. 使用Java 7+提供的try-with-resources语法自动管理文件流,不需要手动写close逻辑,彻底避免资源泄漏。
  4. 抽离公共的文件加载逻辑,消除重复代码。

优化后代码示例

package chapter11;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.NoSuchElementException;

public class LabProgram {
    private static final Map<String, String> nameToId = new HashMap<>();
    private static final Map<String, String> idToName = new HashMap<>();

    // 预加载名册数据
    private static void loadRoster(String fileName) throws IOException {
        try (FileInputStream fis = new FileInputStream(fileName);
             Scanner scanner = new Scanner(fis)) {
            while (scanner.hasNextLine()) {
                String line = scanner.nextLine().trim();
                if (line.isEmpty()) continue; // 跳过空行
                String[] parts = line.split("\\s+", 2);
                if (parts.length == 2) {
                    nameToId.put(parts[0], parts[1]);
                    idToName.put(parts[1], parts[0]);
                }
            }
        }
    }

    public static String findID(String studentName) {
        String id = nameToId.get(studentName);
        if (id == null) {
            throw new NoSuchElementException("Student ID not found for " + studentName);
        }
        return id;
    }

    public static String findName(String studentID) {
        String name = idToName.get(studentID);
        if (name == null) {
            throw new NoSuchElementException("Student name not found for " + studentID);
        }
        return name;
    }

    public static void main(String[] args) {
        Scanner scnr = new Scanner(System.in);
        try {
            // 读取文件名并预加载数据
            String studentInfoFileName = scnr.next();
            loadRoster(studentInfoFileName);

            // 读取查询选项
            int userChoice = scnr.nextInt();
            if (userChoice == 0) {
                String studentName = scnr.next();
                System.out.println(findID(studentName));
            } else {
                String studentID = scnr.next();
                System.out.println(findName(studentID));
            }
        } catch (IOException e) {
            System.out.println("Failed to read roster file: " + e.getMessage());
        } catch (NoSuchElementException e) {
            System.out.println(e.getMessage());
        }
    }
}

内容的提问来源于stack exchange,提问作者Jake

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 22:27:04