randomaccessfile 的 length() 返回底层文件实际字节长度且不缓存,每次调用触发系统调用;setlength() 可扩缩文件逻辑大小但不移动文件指针,扩大会填充未定义字节,截断会丢弃尾部数据,需注意指针位置与并发同步问题。

RandomAccessFile 的 length() 返回当前文件长度,setLength() 可以扩大或截断文件,但不会移动文件指针,也不影响已有数据内容。
length() 是只读的当前大小
调用 length() 会返回底层文件的字节长度(long 类型),它反映的是操作系统中该文件实际占用的字节数。这个值是瞬时快照,不缓存,每次调用都触发一次系统调用(类似 stat)。注意:它和 RandomAccessFile 的当前文件指针位置(getFilePointer)无关——指针可以指向末尾之后(比如 seek(100) 而文件只有 10 字节),但 length() 仍返回 10。
setLength() 可扩大或缩小文件
setLength(long newLength) 直接修改文件逻辑大小:
- 若
newLength > current length:文件被扩展,新增区域内容为未定义(通常为零字节,但 Java 不保证,取决于操作系统和文件系统);原数据保持不变,文件指针位置不变(可能落在新扩区域中,后续 write 会覆盖)。 - 若
newLength :文件被截断,超出 newLength 的字节被丢弃;原文件开头到 newLength 的数据保留。 - 若
newLength == current length:无操作,安全调用。
动态调整大小的典型场景与注意事项
常见用途包括预分配日志文件、清理临时数据、实现稀疏结构。使用时需注意:
- setLength() 不改变 getFilePointer,如果指针在截断点之后,下次 write 会从那里开始(可能越界写入失败或触发扩展)。
- 扩展后写入前建议显式 seek() 到期望位置,避免误写到中间“空洞”处。
- 并发访问时,length() 和 setLength() 均非原子操作,多个线程同时调用可能导致不可预期结果,需外部同步。
- 某些文件系统或只读挂载下 setLength() 可能抛出 IOException(如 “Operation not permitted”)。
简单示例:先扩再写
比如想确保文件至少 1MB,并在末尾追加一条记录:
raf.setLength(1024 * 1024); // 确保至少 1MB
raf.seek(raf.length()); // 移动到实际末尾(可能大于 1MB)
raf.writeUTF("log entry");
这里 setLength 保证空间,seek 确保写入位置正确,两者配合才能可靠追加。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











