Java中BufferedReader的Readline()读取文件返回null问题求助
问题排查与代码修正:BufferedReader读取空文件及学生管理功能实现
首先来说你遇到的BufferedReader.readLine()始终返回null的核心原因:你在代码一开始就创建了BufferedWriter指向目标文件,默认的FileWriter构造方法会直接清空文件内容,这就导致后面用BufferedReader读取的时候,文件已经是空的了,自然返回null。除此之外,代码还有不少逻辑和功能上的问题,我帮你逐一修正:
主要问题梳理与修正点
- 文件操作顺序颠倒:应该先读取原文件的学生数据到集合,再进行添加新学生的操作,最后统一把集合内容写入文件覆盖原内容,而不是先写再读。
- Student类构造方法未初始化成员变量:你的
Student构造方法里只打印了"s",没有把传入的name和id赋值给成员变量,导致后续所有学生对象的属性都是默认值,无法正确存储和展示。 - 缺少学号唯一性检查:添加新学生时,需要遍历已有的
studentList,检查新学号是否已经存在,确保唯一性。 - 边添加边写入文件的逻辑错误:应该等用户完成所有添加操作后,再把整个集合的内容一次性写入文件,覆盖原数据,而不是每添加一个就写一次。
- 缺少用户选择显示学生列表的功能:需要添加菜单选项,让用户选择显示完整学生信息还是仅学号。
- 资源关闭不规范:应该使用try-with-resources语法自动关闭IO资源,避免手动关闭时遗漏或出错。
修正后的完整代码
import java.util.*; import java.io.*; public class TestStudent { public static void main(String[] args) { // 定义文件路径 String filePath = "C:\\Users\\user1\\Desktop\\Students.txt"; ArrayList<Student> studentList = new ArrayList<>(); Scanner sc = new Scanner(System.in); // 第一步:读取原文件中的学生数据到集合 try (BufferedReader br = new BufferedReader(new FileReader(filePath))) { String line; while ((line = br.readLine()) != null) { String[] record = line.split("\t"); // 确保每行数据格式正确(姓名+学号) if (record.length == 2) { Student student = new Student(record[0], record[1]); studentList.add(student); } } } catch (FileNotFoundException e) { // 如果文件不存在,说明是第一次使用,直接创建空集合即可 System.out.println("未找到学生文件,将创建新文件"); } catch (IOException e) { e.printStackTrace(); } // 第二步:允许用户添加新学生,检查学号唯一性 String cont; do { System.out.println("请输入学生姓名:"); String name = sc.next(); String id; // 循环直到输入有效的唯一学号 while (true) { System.out.println("请输入6位数字学号:"); id = sc.next(); Student tempStudent = new Student(name, id); // 检查学号格式是否有效 if (!tempStudent.isValidID()) { System.out.println("学号格式错误!必须是6位数字,请重新输入"); continue; } // 检查学号是否已存在 boolean idExists = false; for (Student s : studentList) { if (s.getId().equals(id)) { idExists = true; break; } } if (idExists) { System.out.println("该学号已存在,请重新输入"); } else { break; } } // 添加合法的新学生到集合 studentList.add(new Student(name, id)); System.out.println("是否继续添加学生?(y/n)"); cont = sc.next(); } while (cont.equalsIgnoreCase("y")); // 第三步:将集合中的所有学生数据覆盖写入文件 try (BufferedWriter bw = new BufferedWriter(new FileWriter(filePath))) { for (Student s : studentList) { bw.write(s.getName() + "\t" + s.getId()); bw.newLine(); } System.out.println("学生数据已成功保存到文件"); } catch (IOException e) { e.printStackTrace(); } // 第四步:提供显示选项 System.out.println("请选择显示方式:"); System.out.println("1. 显示完整学生列表"); System.out.println("2. 仅显示学生学号"); int choice = sc.nextInt(); switch (choice) { case 1: System.out.println("完整学生列表:"); for (Student s : studentList) { System.out.println(s.toString()); } break; case 2: System.out.println("学生学号列表:"); for (Student s : studentList) { System.out.println(s.getId()); } break; default: System.out.println("无效选项,退出显示"); } sc.close(); } } class Student { private String name; private String id; // 修正构造方法,正确初始化成员变量 public Student(String name, String id) { this.name = name; this.id = id; } // Getter方法 public String getName() { return this.name; } public String getId() { return this.id; } // Setter方法 public void setName(String name) { this.name = name; } public void setId(String id) { this.id = id; } // 重写toString方法,返回清晰的学生信息 @Override public String toString() { return "学生姓名:" + getName() + ",学号:" + getId(); } // 检查学号是否为6位数字 public boolean isValidID() { if (id.length() != 6) { return false; } for (char c : id.toCharArray()) { if (!Character.isDigit(c)) { return false; } } return true; } }
代码说明
- 文件读取逻辑:先用
BufferedReader读取原文件内容到集合,如果文件不存在则捕获FileNotFoundException,提示用户将创建新文件。 - 学号验证:添加学生时先检查学号格式(6位数字),再遍历集合检查学号是否已存在,确保唯一性。
- 文件写入逻辑:用户完成添加后,用
BufferedWriter将整个集合的内容一次性写入文件,覆盖原数据。 - 显示功能:提供菜单选项,让用户选择显示完整信息或仅学号。
- 资源管理:使用try-with-resources自动关闭IO流,避免资源泄漏。
内容的提问来源于stack exchange,提问作者Maizere Pathak.Nepal
相关产品推荐
相关产品推荐

