arraylist不能直接写入文件,因其为内存对象,序列化后为不可读二进制格式,易因类结构或jdk版本变化导致反序列化失败;应优先使用utf-8编码的纯文本(如每行一条)或json格式,并注意处理换行、编码和字段访问权限问题。

为什么 ArrayList 不能直接写进文件就完事?
因为 ArrayList 是内存对象,序列化后默认是二进制格式(比如用 ObjectOutputStream),人看不懂、不好调试,也容易因类结构变动导致反序列化失败。更麻烦的是,不同 JDK 版本、甚至同一项目里改了个字段名,readObject() 就可能抛 InvalidClassException。
实操建议:
- 优先用纯文本格式:JSON 或每行一条任务的简单文本(如
2024-05-20|买牛奶|false) - 避免
Serializable+ObjectOutputStream,除非你明确控制版本且不打算人工查看数据 - 如果选 JSON,用
gson或org.json,别手写解析——容易漏转义、错判空值
怎么把 List<string></string> 存成可读文件并安全读回来?
最轻量的做法是按行存:每条待办占一行,用 Files.write() 和 Files.readAllLines(),不依赖额外库,JDK 7+ 原生支持。
常见错误现象:
立即学习“Java免费学习笔记(深入)”;
- 用
PrintWriter.println()写完没flush()或close()→ 文件为空或部分内容丢失 - 读文件时忽略编码,默认平台编码(Windows 是 GBK)→ 中文变乱码
- 任务内容含换行符(比如用户输入了多行描述)→ 一行变多行,读取错位
实操建议:
- 写入时统一用 UTF-8:
Files.write(path, lines, StandardCharsets.UTF_8) - 读取时同样指定编码:
Files.readAllLines(path, StandardCharsets.UTF_8) - 如果任务内容可能含换行或分隔符,改用 JSON;否则就约定“不允许输入换行”,并在 UI 层截断
用 Gson 存 List<todoitem></todoitem> 遇到 IllegalAccessException 怎么办?
因为 Gson 默认只序列化 public 字段或 getter/setter,如果你的 TodoItem 类全是 private String title 却没写 getTitle(),Gson 就会跳过它,甚至报反射权限异常(尤其在 JDK 17+ 模块限制下)。
实操建议:
- 给每个字段补上 public getter(哪怕只是
public String getTitle() { return title; }) - 或者用
GsonBuilder().excludeFieldsWithoutExposeAnnotation().create(),然后在字段上加@Expose - 别用
new Gson().toJson(list)直接怼——先测试单个对象:System.out.println(gson.toJson(new TodoItem("test", false))),确认输出符合预期
示例片段:
class TodoItem {
private String title;
private boolean done;
// 必须有 getter
public String getTitle() { return title; }
public boolean isDone() { return done; }
}
每次增删都要全量重写文件,会不会慢或丢数据?
对几百条以内的待办清单,全量写入完全没问题。但真要防崩溃丢数据,关键不是“增量”,而是“先写临时文件,再原子替换”。
性能 / 兼容性影响:
- 小文件(
- 直接
Files.write(path, ...)是覆盖操作,若中途断电,原文件已清空,新内容没写完 → 数据全丢 - Windows 下用
Files.move(tempPath, path, StandardCopyOption.REPLACE_EXISTING)是原子的;Linux/macOS 同理
实操建议:
- 写之前生成临时路径:
Path temp = Paths.get(path.toString() + ".tmp") - 写入
temp,成功后再move替换原文件 - 最后记得
try { Files.deleteIfExists(temp); } catch (IOException ignored) {}
真正容易被忽略的是:没做文件操作异常处理。比如磁盘满、权限不足、路径含非法字符(?、),这些都会让 <code>Files.write() 抛 IOException,而很多人只 catch 了 Exception,漏掉具体原因。










