用 seek(100) 精确跳转到第100字节(从0开始),再读取;write(int) 只写1字节,应改用 writeInt() 写4字节整数;RandomAccessFile 本身跨平台安全,但 writeUTF() 与手动 getBytes() 不兼容;它非线程安全,多线程需加锁或改用 FileChannel。

RandomAccessFile 怎么跳到文件第100字节开始读?
靠 seek(),不是 skipBytes()。后者只对输入流有效,且行为不可靠——它可能少跳、不跳甚至抛 IOException,尤其在底层是管道或网络流时(虽然 RandomAccessFile 不是,但习惯上别混用)。
实操建议:
-
seek(100)精确移动到第100字节(从0开始计数),下次readByte()或readInt()就从这儿起读 - 调用前先确认文件长度,用
length(),避免IOException: Attempt to seek before beginning of file - 注意:
seek()不影响写入位置,读写共用一个文件指针——写也会从当前指针位置覆盖
用 RandomAccessFile 写 int 为什么文件里多出 3 个乱码字节?
因为你用了 write(int),它只写低8位(1字节),而你想写的是4字节的整数。Java 的 int 是32位,必须用 writeInt(int) 才能完整、按大端序写入。
常见错误现象:
立即学习“Java免费学习笔记(深入)”;
- 用
write(123456)→ 实际只写入0x40(123456 & 0xFF),剩下高24位全丢 - 用
writeBytes("123")写字符串 → 每个字符按单字节写,中文直接变乱码(没编码转换)
正确姿势:
- 写基本类型:用
writeInt()、writeLong()、writeDouble()等配套方法 - 写字符串:先转字节数组,如
write("hello".getBytes(StandardCharsets.UTF_8)),别用writeBytes() - 写完记得
flush()(虽然RandomAccessFile不缓冲,但配合getFD().sync()可强制落盘)
RandomAccessFile 在 Windows 和 Linux 下读写同一二进制文件会错位吗?
不会,只要不用 writeUTF() 或换行相关方法。它的所有 readXxx() / writeXxx() 都是纯字节操作,与平台无关。
但容易踩的坑是:你误用了平台相关的换行符逻辑。
-
writeUTF()会先写2字节长度,再写修改UTF-8内容 —— 这个格式跨平台安全,但和手动写String.getBytes()不兼容 -
writeBytes(String)和writeChars(String)已废弃,前者按 ISO-8859-1 写,后者每个字符写2字节(含高位0),Windows/Linux 表现一致,但语义诡异,别用 - 真正跨平台敏感点是文件编码(比如你用
new String(bytes, "GBK")解析,Linux 默认没 GBK 支持)——但这和RandomAccessFile本身无关
多个线程同时用同一个 RandomAccessFile 实例读写会怎样?
大概率数据错乱,而且不报错。因为 RandomAccessFile 的 seek() + read() / write() 不是原子操作,中间可能被其他线程打断。
使用场景限制很明确:它不是线程安全的。
- 并发读写同一文件 → 必须自己加锁(比如
synchronized(file)),或改用FileChannel配合ByteBuffer和显式 position 控制 - 多个实例操作同一文件 → 各自维护独立指针,但写操作仍可能覆盖(OS 层面无协调),需应用层协议(如固定区域划分)
- 如果只是“一个写、多个读”,且读取前都
seek()到确定位置,风险较低,但仍建议加读锁防止写线程中途seek()干扰
真正难处理的是指针状态和 I/O 的分离——你以为 seek() 了,其实下一行还没执行,别的线程已经把指针拽走了。这种隐式共享比显式共享更易漏掉。










