学生管理系统 - 新增文本文件与二进制文件的存储系统

学生管理系统 - 新增文本文件与二进制文件的存储系统

目的:

  • 新增文本文件与二进制文件的存储系统
  • 存在乱码问题
  • 分析优化解决该问题

一、系统存储设计核心思路

1. 双存储策略:二进制文件(精准存储类型)+ 文本文件(可读备份),兼顾数据精度与可读性。
2. 保存机制:添加/删除后自动保存 + 选项0手动保存,双重保障数据不丢失。
3. 优化目标:解决文本文件乱码、缓冲区未刷新、代码冗余、异常处理不清晰等问题,保持原功能不变。

二、原代码(文件保存相关核心截取)

1. 二进制文件保存(StudentManagementSystem.java)

public void saveStudentsBin() throws IOException {
    try (DataOutputStream dos = new DataOutputStream(new FileOutputStream(filename))) {
        dos.writeInt(students.size()); // 写入学生总数
        for (Student s : students) {
            dos.writeUTF(s.getName());
            dos.writeInt(s.getAge());
            dos.writeUTF(s.getGender());
            dos.writeUTF(s.getId());
            dos.writeUTF(s.getMajor());
            dos.writeDouble(s.getGpa());
        }
    }
}

通过FileOutputStream在文件filename中关联文件,再包装成DataOutputStream,根据列表的长度遍历每个学生对象,按照“姓名,年龄,性别,id,专业,绩点”的顺序将每个属性对应的数据类型写入文件。

2. 文本文件保存(StudentManagementSystem.java)

public void saveStudents() throws IOException {
    FileWriter fw = null;
    try {
        fw = new FileWriter(filename1);
        for (Student s : students) {
            fw.write(s.getName());
            fw.write(s.getAge());       // 问题1:写入ASCII码,导致乱码
            fw.write(s.getGender());
            fw.write(s.getId());
            fw.write(s.getMajor());
            fw.write((int) s.getGpa()); // 问题2:强制转int丢失精度,且写入ASCII码
        }
        fw.flush(); // 已修复:最初遗漏导致写入失败
    } catch (Exception e) {
        throw new RuntimeException(e); // 问题3:异常信息不明确
    }
}

使用字符流FileWriter关联filename1,准备写入文本,根据列表的长度遍历每个学生对象,按照“姓名,年龄,性别,id,专业,绩点”的顺序将每个属性对应的数据类型写入文件。

3. 保存触发逻辑(Main.java)

// 手动保存(case0)
case 0:
    try {
        sms.saveStudentsBin();
        System.out.println("数据已成功保存到文件!(二进制)");
        sms.saveStudents();
        System.out.println("数据已成功保存到文件!(文本文件)");
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
    break;

// 添加后自动保存(case1片段)
try {
    sms.saveStudentsBin();
    System.out.println("数据已成功保存到文件!");
    sms.saveStudents();
    System.out.println("数据已成功保存到文件!(文本文件)");
} catch (IOException e) {
    throw new RuntimeException(e);
}

main类当中额外添加了一个选项0,做添加或者删除后的总体文件写入以及保存,当然我在添加或者删除学生信息的模块当中也有做信息的写入,在选项7退出系统后会看见文件成功出现在列表。

三、优化代码(文件保存相关核心截取)

1. 核心优化点说明

优化方向 原问题 优化方案
文本文件格式 数值写入ASCII码,无分隔符,乱码 转为字符串+分隔符,每行存储一个学生信息
资源关闭 FileWriter未自动关闭,依赖flush 改用try-with-resources自动关闭,无需手动flush
代码冗余 重复调用两个保存方法 提取公共saveAll()方法,统一触发双存储
异常处理 异常信息模糊,掩盖问题 打印具体错误信息,保留原异常链
空值兼容 字符串为null时可能抛异常 添加null判断,避免NullPointerException

2. 优化后的存储类代码(StudentManagementSystem.java)

public class StudentManagementSystem {
    private List<Student> students;
    String filename = "Students.data";  // 二进制文件路径
    String filename1 = "Student.txt";   // 文本文件路径

    // 初始化学生列表
    public StudentManagementSystem() {
        students = new ArrayList<>();
    }

    // 【优化1:二进制文件保存 - 增加空值兼容】
    public void saveStudentsBin() throws IOException {
        try (DataOutputStream dos = new DataOutputStream(new FileOutputStream(filename))) {
            dos.writeInt(students.size()); // 写入学生总数
            for (Student s : students) {
                // 处理null值,避免NullPointerException
                dos.writeUTF(s.getName() == null ? "" : s.getName());
                dos.writeInt(s.getAge());
                dos.writeUTF(s.getGender() == null ? "" : s.getGender());
                dos.writeUTF(s.getId() == null ? "" : s.getId());
                dos.writeUTF(s.getMajor() == null ? "" : s.getMajor());
                dos.writeDouble(s.getGpa());
            }
        }
    }
  • 做对null值的处理
    // 【优化2:文本文件保存 - 解决乱码、自动关闭、格式规范】
    public void saveStudentsText() throws IOException {
        // try-with-resources自动关闭FileWriter,无需手动flush/close
        try (FileWriter fw = new FileWriter(filename1)) {
            for (Student s : students) {
                // 格式:姓名,年龄,性别,学号,专业,GPA\n(分隔符+换行,清晰可读)
                String studentLine = String.format(
                    "%s,%d,%s,%s,%s,%.2f%n",
                    s.getName() == null ? "" : s.getName(),
                    s.getAge(),
                    s.getGender() == null ? "" : s.getGender(),
                    s.getId() == null ? "" : s.getId(),
                    s.getMajor() == null ? "" : s.getMajor(),
                    s.getGpa()
                );
                fw.write(studentLine); // 写入字符串,无乱码
            }
        } catch (IOException e) {
            // 优化3:明确异常信息,便于调试
            throw new IOException("文本文件保存失败:" + e.getMessage(), e);
        }
    }
  • 使用了try-with-resources 的形式,以及定义了字符串格式并且添加了换行,使得保存的文本更美观,以及对null值做了特殊处理。
    // 【优化4:提取公共方法,减少代码冗余】
    public void saveAll() throws IOException {
        saveStudentsBin();   // 先保存二进制文件(核心存储)
        saveStudentsText();  // 再保存文本文件(备份)
    }

    // 其他业务方法(增删查)保持不变...
}
  • 通过一次性调用两个方法构成一个新方法,可以直接在0选项中一次性调用,避免代码拖沓。

3. 优化后的保存触发逻辑(Main.java)

// 手动保存(case0)- 优化后:调用公共方法,代码简洁
case 0:
    try {
        sms.saveAll(); // 统一触发双存储保存
        System.out.println("二进制文件(Students.data)和文本文件(Student.txt)保存成功!");
    } catch (IOException e) {
        System.err.println("保存失败:" + e.getMessage()); // 打印具体错误
    }
    break;

// 添加后自动保存(case1片段)- 优化后
try {
    sms.saveAll(); // 统一调用,减少冗余
    System.out.println("学生添加成功,数据已自动保存!");
} catch (IOException e) {
    System.err.println("添加后保存失败:" + e.getMessage());
}
break;

// 删除后自动保存(case2片段)- 优化后
try {
    sms.saveAll(); // 统一调用
    System.out.println("学生删除成功,数据已自动保存!");
} catch (IOException e) {
    System.err.println("删除后保存失败:" + e.getMessage());
}
break;

四、优化后效果验证

1. 文本文件可读性

  • 原文本文件内容(乱码):
    image
  • 原因:
  • 数值写入ASCII码,无分隔符,乱码
  • 字符串为null时可能抛异常
  • 优化后文本文件内容(清晰):
    image

2. 代码可维护性

  • 减少重复代码:原代码重复调用2次保存方法,优化后只需调用saveAll()
  • 异常可调试:明确打印“文本文件保存失败:路径不存在”等具体信息,快速定位问题。

3. 兼容性提升

  • 支持空值:若学生姓名、性别等为null,会自动转为空字符串,避免程序崩溃。
  • 精度保留:GPA以%.2f格式保存(如3.8→3.80),不丢失精度。

五、关键注意细节

  1. 二进制文件:写入顺序(姓名→年龄→性别→...)必须与后续读取顺序一致,否则解析错乱。
  2. 文本文件:分隔符(如逗号)需避免出现在学生字段中(如姓名含逗号需改用其他分隔符,如|)。
  3. 文件路径:默认生成在项目根目录,若需指定绝对路径(如"d:/Students.data"),需确保路径存在。
  4. 原功能保留:优化后不改变“自动保存+手动保存”的核心机制,仅提升稳定性和可读性。

六、运行截图

image

添加学生信息
chen 19 female 1 sc 4.0
siying 19 female 2 biology 4.0
mali 18 male 3 law 3.8

image

删除学生信息 删除id为2的学生,输入选项0进行保存,随后7退出系统,查看文件。
文本文件
image

出现乱码

二进制文件
image

image

可见确实是删掉了id为2的学生信息,但是会发现绩点那一栏出现了乱码。


再根据AI提供的优化代码后进行修改,以及按照原步骤进行修改,输入原信息
文本文件
image
二进制文件
image

posted @ 2025-11-23 21:03  才知风自由  阅读(19)  评论(2)    收藏  举报