RandomAccessFile 实现高速追加的关键是用 length() 获取文件长度后直接 seek(raf.length()) 定位到末尾写入,避免逐行扫描;需注意编码一致、手动添加匹配换行符,并发时须同步或改用 APPEND 模式。

RandomAccessFile 本身不提供“高速追加”的魔法,但它的指针定位能力配合合理使用,能避免读取整个文件,实现真正意义上的末尾追加——关键在于:**跳过内容扫描,直接定位到文件末尾写入**。
为什么不用 seek(0) 或逐行扫描?
大型日志文件(GB 级)若用 readLine() 从头遍历找末尾,I/O 开销巨大,且 RandomAccessFile 的 readLine 是同步、单字节扫描的,极慢。而 seek(fileLength) 是 O(1) 操作,内核直接将文件指针置到末尾偏移量,无数据读取开销。
正确做法:用 length() 获取长度,再 seek() 到末尾
这是最轻量、最可靠的方式:
通过 yarn-threads-cli 与 Threads(Meta)交互。当用户想要阅读首页动态、点赞、收藏的帖子或特定帖子时使用;查看...
- 调用
raf.length()获取当前文件字节长度(底层是stat()系统调用,极快) - 立即执行
raf.seek(raf.length())—— 此时指针就停在 EOF 位置 - 直接 write/writeUTF/writeBytes 写入新日志行(注意手动添加换行符,如
"\n") - 无需 flush()(除非你禁用了 OS 缓存,一般 write 后 close 会自动落盘)
注意编码与换行一致性
追加内容必须与原日志文件编码一致(如 UTF-8),否则可能损坏文本;换行符也要匹配已有格式(Linux 用 "\n",Windows 日志可能用 "\r\n")。建议:
- 打开时明确指定字符集(通过 OutputStreamWriter 包装更安全,但 RandomAccessFile 本身只支持字节写)
- 若写字符串,先用
str.getBytes(StandardCharsets.UTF_8)转字节数组再 write - 写完一行后,显式 write 换行符字节,确保每条日志独立成行
并发追加需额外同步
RandomAccessFile 不是线程安全的。多个线程/进程同时 seek + write 可能导致覆盖或错位。实际生产中建议:
- 单进程内:用
synchronized(raf)或 ReentrantLock 保护写操作 - 跨进程:改用
FileChannel.open(..., StandardOpenOption.APPEND),它由 OS 保证 append 原子性(推荐) - 或使用带日志轮转和异步刷盘的成熟框架(Log4j2、Logback)
不复杂但容易忽略:真正“高速”的核心,就是绕过所有内容解析,靠 length() 和 seek() 实现零扫描定位。其他都是细节保障。

















