Java中使用Scanner逐行读取员工文件并存储记录的实现问题
问题分析与解决方案
你的代码存在几个关键问题,导致无法实现"逐行读取并将记录存入List"的需求:
- 方法参数
scanner被重新赋值,外部传入的实例完全没用上; - 使用
StringBuilder拼接所有行,没有按行存入List; line.operator是拼写错误,正确的系统属性是line.separator,但这里其实不需要,因为scanner.nextLine()已经会读取完整一行;- 缺少异常的针对性处理,且没有返回或保存读取到的记录。
以下是两种解决方案,分别对应不同的使用场景:
方案1:直接存储每行原始记录到List
适合仅需保留原始行数据的场景:
import java.io.File; import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class EmployeeFileHandler { private File employeeFile; public EmployeeFileHandler(File employeeFile) { this.employeeFile = employeeFile; } public List<String> readEmployeeRecords() { List<String> records = new ArrayList<>(); if (!employeeFile.exists()) { System.err.println("文件不存在:" + employeeFile.getAbsolutePath()); return records; } // try-with-resources自动关闭Scanner,避免资源泄漏 try (Scanner scanner = new Scanner(employeeFile)) { while (scanner.hasNextLine()) { String line = scanner.nextLine().trim(); // 跳过空行,过滤无效数据 if (!line.isEmpty()) { records.add(line); System.out.printf("已读取第%d条记录:%s%n", records.size(), line); } } } catch (FileNotFoundException e) { System.err.println("无法读取文件:" + e.getMessage()); } catch (Exception e) { System.err.println("读取过程中发生错误:" + e.getMessage()); } return records; } }
方案2:解析为自定义Employee对象(更实用)
如果需要提取员工的结构化信息,建议定义Employee类并解析每行数据:
第一步:定义Employee类
public class Employee { private String type; // 员工类型:D/A private int id; private String name; private String dob; private String address; private String employeeNumber; // D类员工专属工号 private String statusOrPosition; // D类是状态,A类是职位 // D类员工构造方法 public Employee(String type, int id, String name, String dob, String address, String empNum, String status) { this.type = type; this.id = id; this.name = name; this.dob = dob; this.address = address; this.employeeNumber = empNum; this.statusOrPosition = status.replace("'", ""); // 去除状态字段的单引号 } // A类员工构造方法(无工号字段) public Employee(String type, int id, String name, String dob, String address, String position) { this.type = type; this.id = id; this.name = name; this.dob = dob; this.address = address; this.statusOrPosition = position; } @Override public String toString() { return String.format("[%s] ID:%d 姓名:%s 生日:%s 地址:%s %s:%s", type, id, name, dob, address, type.equals("D") ? "工号" : "职位", type.equals("D") ? employeeNumber : statusOrPosition); } // 按需添加getter/setter方法 }
第二步:实现读取与解析逻辑
import java.io.File; import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class EmployeeFileHandler { private File employeeFile; public EmployeeFileHandler(File employeeFile) { this.employeeFile = employeeFile; } public List<Employee> parseEmployeeRecords() { List<Employee> employees = new ArrayList<>(); if (!employeeFile.exists()) { System.err.println("文件不存在:" + employeeFile.getAbsolutePath()); return employees; } try (Scanner scanner = new Scanner(employeeFile)) { while (scanner.hasNextLine()) { String line = scanner.nextLine().trim(); if (line.isEmpty()) continue; // 按", "分割字段(注意逗号后有空格) String[] fields = line.split(", "); try { if ("D".equals(fields[0])) { // D类字段:类型, ID, 姓名, 生日, 地址, 工号, 状态 Employee emp = new Employee( fields[0], Integer.parseInt(fields[1]), fields[2], fields[3], fields[4], fields[5], fields[6] ); employees.add(emp); } else if ("A".equals(fields[0])) { // A类字段:类型, ID, 姓名, 生日, 地址, 职位 Employee emp = new Employee( fields[0], Integer.parseInt(fields[1]), fields[2], fields[3], fields[4], fields[5] ); employees.add(emp); } } catch (ArrayIndexOutOfBoundsException | NumberFormatException e) { System.err.println("解析行失败,跳过该行:" + line); } } } catch (FileNotFoundException e) { System.err.println("文件未找到:" + e.getMessage()); } return employees; } // 测试示例 public static void main(String[] args) { EmployeeFileHandler handler = new EmployeeFileHandler(new File("employees.txt")); List<Employee> employees = handler.parseEmployeeRecords(); System.out.println("共解析到" + employees.size() + "条有效员工记录:"); for (Employee emp : employees) { System.out.println(emp); } } }
关键改进说明
- 使用try-with-resources管理Scanner资源,无需手动关闭,避免资源泄漏;
- 跳过空行,过滤无效数据;
- 针对D/A两类员工的不同字段结构做了适配,处理了状态字段的单引号问题;
- 捕获解析时的异常,避免单条错误记录导致整个读取流程终止;
- 返回存储结果的List,满足需求。
内容的提问来源于stack exchange,提问作者Hải Đăng
相关产品推荐
相关产品推荐

