Java大学选课项目中如何校验用户输入的学生ID是否已被占用
现有代码的核心逻辑硬伤
- 文件写入模式错误:使用默认的覆盖模式初始化
FileOutputStream,每次新建学生都会把StudentInfo.dat中存储的所有历史学生数据全部清空,根本留存不住过往的学生ID,后续的ID比对完全没有数据基础 - 流程顺序颠倒:当前逻辑是先把学生的全部信息(包括用户输入的ID)写完落盘,才启动读文件做校验的流程,等于重复ID的信息已经覆盖写入文件了,校验完全起不到拦截作用
- 读文件逻辑不完整:原计划循环读文件匹配ID,但没有处理读到文件末尾的终止判断,运行时会直接抛出流读到尾的IO异常
- 缺少文件存在性判断:如果是第一次运行程序还没有生成学生存储文件,直接读文件会直接抛出文件不存在的异常
可落地的校验实现流程
完全顺着数据生命周期的逻辑走,不需要复杂的结构:
- 先做数据预热:进入创建学生流程后,首先判断
StudentInfo.dat文件是否存在- 文件不存在:说明系统里还没有任何学生,不存在ID占用问题
- 文件存在:开输入流按之前写文件的存储顺序,把所有历史学生的ID全部读出来,存在一个临时的
Set集合里(Set自带去重属性,查重复的效率很高)
- 把ID校验环节前置:不要先让用户填半天姓名、地址等信息,最后才告知ID重复做无用功
- 引导用户输入ID,和刚才读出来的历史ID集合做匹配
- 匹配到重复值:立刻提示“该学生ID已被占用,请重新输入”,循环直到用户输入的ID不在历史集合里为止
- 修改文件写入模式:把文件输出流改成追加模式,写新学生数据时在文件末尾追加内容,不会覆盖原有存储的学生信息
- 等用户把剩余的姓名、地址、城市、州等信息填写完成,再把整条学生数据一次性追加写入文件
参考实现的CreateStudent方法
import java.io.*; import java.util.HashSet; import java.util.Scanner; import java.util.Set; public static void CreateStudent() throws IOException { Set<Integer> existedIDs = new HashSet<>(); File studentFile = new File("StudentInfo.dat"); // 第一步:如果文件存在,提前读出所有历史学生ID if (studentFile.exists()) { try (DataInputStream inputFile = new DataInputStream(new FileInputStream(studentFile))) { while (true) { try { // 按存储顺序依次读字段:姓名、地址、城市、州 inputFile.readUTF(); inputFile.readUTF(); inputFile.readUTF(); inputFile.readUTF(); // 读到ID字段就存进集合 int oldID = inputFile.readInt(); existedIDs.add(oldID); } catch (EOFException e) { // 读到文件末尾就跳出循环 break; } } } } Scanner keyboard = new Scanner(System.in); int newStudentID; // 循环校验ID,直到拿到不重复的合法ID while (true) { System.out.print("请输入学生ID(1-10): "); newStudentID = keyboard.nextInt(); if (existedIDs.contains(newStudentID)) { System.out.println("该ID已被占用,请更换后重试!"); continue; } System.out.println("ID可用,请继续填写后续信息"); // 吃掉nextInt残留的换行符,避免后面nextLine读到空内容 keyboard.nextLine(); break; } // 收集剩余的学生信息 System.out.print("请输入学生全名: "); String fullName = keyboard.nextLine(); System.out.print("请输入居住地址: "); String address = keyboard.nextLine(); System.out.print("请输入所在城市: "); String city = keyboard.nextLine(); System.out.print("请输入所在州: "); String state = keyboard.nextLine(); // 以追加模式写入文件,不覆盖原有历史数据 try (DataOutputStream outputFile = new DataOutputStream(new FileOutputStream(studentFile, true))) { outputFile.writeUTF(fullName); outputFile.writeUTF(address); outputFile.writeUTF(city); outputFile.writeUTF(state); outputFile.writeInt(newStudentID); } System.out.println("学生信息创建完成"); }
小提醒:代码里用了try-with-resources的写法,打开的文件流会自动关闭,不用手动调用
close(),能避免资源泄漏的问题。
内容的提问来源于stack exchange,提问作者Tom Ronaldo
相关产品推荐
相关产品推荐

