RandomAccessFile.readLine()默认用ISO-8859-1解码,不支持UTF-8/GBK等中文编码,导致乱码;应改用BufferedReader+InputStreamReader指定编码,或手动读字节后按指定编码解码。

Java 中 RandomAccessFile 的 readLine() 方法默认使用 ISO-8859-1 编码读取字节并转换为字符串,无法正确解析 UTF-8 或 GBK 等中文编码,导致中文乱码。根本原因是该方法不支持指定字符集,且换行符识别逻辑也与现代编码不兼容。
避免使用 readLine() 读取中文
RandomAccessFile.readLine() 已被官方标记为“不推荐用于新代码”,它按字节逐个读取直到遇到 \n、\r 或 \r\n,再用 ISO-8859-1 解码——这对含多字节的中文(如 UTF-8 中一个汉字占 3 字节)必然出错。例如“你好”在 UTF-8 下是 0xE4 0xBD 0xA0 0xE4 0xBD 0xA1,ISO-8859-1 会把每个字节当独立字符解成乱码符号。
- 不要依赖
readLine()处理含中文的文本文件 - 即使文件是 GBK 编码,
readLine()同样失败,因 GBK 中汉字也是双字节,而 ISO-8859-1 无法还原
改用 BufferedReader + 指定编码读取
若需按行读取中文内容,应绕过 RandomAccessFile 的文本能力,转用基于字符流的标准方式:先用 FileInputStream 包装文件,再用 InputStreamReader 指定编码(如 "UTF-8"),最后套上 BufferedReader。
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
- 示例代码:
File file = new File("data.txt");
try (FileInputStream fis = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
BufferedReader br = new BufferedReader(isr)) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line); // 中文正常显示
}
}
- 注意:这种方式失去
RandomAccessFile的随机定位能力(如seek()),适合顺序读取 - 若必须随机访问某一行,可先用此方式加载全部行到
List<string></string>,再按索引取值
保留 RandomAccessFile + 手动解码字节
若确实需要 RandomAccessFile 的 seek()、getFilePointer() 等能力(如解析二进制混合文本格式),则需自行读取字节块,再用指定编码解码为字符串。
立即学习“Java免费学习笔记(深入)”;
- 步骤:用
read(byte[])读取一批字节 → 找到行尾位置(如扫描\n)→ 截取对应字节数组 →new String(bytes, "UTF-8") - 注意:不能直接用
readLine(),也不能用readUTF()(它读的是 Java 特定的 modified UTF-8,非标准 UTF-8) - 换行符需按实际文件格式判断:Linux 是
\n,Windows 是\r\n,macOS 旧版是\r
写入时也需统一编码
读乱码往往伴随写乱码。用 RandomAccessFile.writeBytes(String) 写中文时,同样按平台默认编码(通常是 ISO-8859-1)写入字节,导致文件内容本身已损坏。正确做法是:
- 用
String.getBytes("UTF-8")获取字节数组,再调用write(byte[]) - 或改用
FileOutputStream+OutputStreamWriter写入,确保编码一致 - 务必保证读写两端使用完全相同的字符集,否则必然乱码

















