randomaccessfile追加写入需先seek到末尾,因其写入总在当前指针位置发生;正确做法是raf.seek(raf.length())后writebytes(str+"\n");注意线程不安全,多线程需同步或改用filechannel。

RandomAccessFile 在文件末尾追加写入时,必须先调用 seek(length),否则写入会从当前文件指针位置开始(可能覆盖已有内容),而不是真正“追加”。
为什么不能直接 write()?
RandomAccessFile 默认不提供类似 FileWriter 的 append = true 模式。它的写入总是在当前文件指针位置发生。如果没显式移动指针,指针可能停在开头或中间,导致覆盖而非追加。
所以“追加”的本质是:把指针移到文件末尾,再写入。
正确做法:先 seek 到末尾,再 write
获取当前文件长度并定位:
- 用
file.length()获取字节长度(即末尾偏移量) - 用
file.seek(file.length())将指针移到末尾(注意:length 是下一个可写位置,不是最后一个字节索引) - 再调用
writeXXX()方法写入内容
示例:
RandomAccessFile raf = new RandomAccessFile("data.txt", "rw");
raf.seek(raf.length()); // 定位到末尾
raf.writeUTF("新一行内容\n"); // 追加写入
raf.close();
注意字符编码与换行问题
writeUTF() 写入的是修改版 UTF-8,带长度前缀,不适合纯文本追加;日常追加推荐用 writeBytes(String) 或 writeChars(String)(后者按 char 写,双字节,慎用)。
更稳妥的方式:
- 用
writeBytes(str + "\n")追加字符串(按平台默认编码解释字节,适合 ASCII/UTF-8 环境) - 若需严格 UTF-8,可先用
str.getBytes(StandardCharsets.UTF_8),再用write(byte[]) - 记得手动加换行符,因为 seek 不自动处理格式
线程安全与资源管理提醒
RandomAccessFile 本身不保证多线程写入安全。多个线程同时 seek+write 可能相互干扰(例如 A 获取 length、B 也获取 length、A/B 同时 seek 并写入,造成错位或覆盖)。
建议:
- 单线程场景下直接使用
- 多线程场景下加同步(如
synchronized(raf)),或改用FileChannel配合position(length)和原子写入 - 务必用 try-with-resources 或 finally 关闭,避免句柄泄漏
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











