问题结论

为什么 RandomAccessFile 的 readLine() 读 UTF-8 文件是乱码?

RandomAccessFile 的函数 readLine() 使用 ISO-8859-1 解码文件,所以读取 UTF-8 的文件会造成乱码。解决方式就是再使用ISO-8859-1编码得到原先的byte[]数组,再用这个数组重新构造 String 即可。

但是使用ISO-8859-1解码并没有在文档中提及,这个隐藏特性的来源是什么呢?

源码之下,了无秘密

首先查看 readLine() 的源码

public final String readLine() throws IOException {

StringBuffer input = new StringBuffer();

int c = -1;

boolean eol = false;

while (!eol) {

switch (c = read()) {

case -1:

case '\n':

eol = true;

break;

case '\r':

eol = true;

long cur = getFilePointer();

if ((read()) != '\n') {

seek(cur);

}

break;

default:

input.append((char)c);

break;

}

}

if ((c == -1) && (input.length() == 0)) {

return null;

}

return input.toString();

}

readLine 实际上就是通过迭代 read() 函数读取单个字节,并把每个字节转化成 char 类型依次装入 input 中,在遇到换行符之后停止操作。这里我们可以注意到有趣的一点,就是他对于不同协议中的两种换行符都做了考虑。

所以我们继续探索 read() 函数

read() 源码

public int read() throws IOException {

return read0();

}

read() 函数非常的简单,通过注释我了解到,read() 的作用就是读取一个字节的内容,并把这个字节装入 int 中返回。

思考

再回头看 readLine(),这两个函数都非常的简单,无论是代码还是注释根本就没有提什么 ISO-8859-1标准,那这一行是怎么莫名其妙的被以 ISO-8859-1 解码的呢。

这是因为,Java 的 char 类型使用的是Unicode。而ISO-8859-1是一位定长的字符集,Unicode 的前256位和ISO-8859-1是重合的。换句话说,Unicode的前256位就是ISO-8859-1。所以在 readLine() 中对每一字节进行读取并立即转化成 char 类型的过程,就相当于完成了 ISO-8859-1 解码。

而我们要想得到原始的 byte 串怎么办呢?有两种方法,一种就是把 readLine() 读出的 String 用 ISO-8859-1 编码转回 编码前的 byte[] 数组。

import java.io.IOException;

import java.io.RandomAccessFile;

public class LearnBytes {

public static void main(String[] args) throws IOException {

String path = "files/t.txt";

RandomAccessFile rf = new RandomAccessFile(path, "rw");

String buffer = rf.readLine();

byte[] originalBytes = buffer.getBytes("ISO-8859-1”); //反编码回文件中本原始的字节流

String utf8 = new String(originalBytes); //String 构造函数默认接受 UTF-8 编码

}

}

另一种方法就是通过 read() 自己写一个readLine()函数,返回值是byte[]类型。

总结

It’s not a bug. It’s an undocumented feature.

参考及补充

严格来讲,ISO-8859-1 和 Java char 使用的 Unicode 是字符集。而 UTF-8 是基于 Unicode 的编码方式。

java randomaccessfile 乱码_Java 8 RandomAccessFile 读取 UTF-8 乱码相关推荐

  1. java 读写文件乱码_Java 解决读写本地文件中文乱码的问题

    Java 解决读写本地文件中文乱码的问题 前言: 在用Java程序进行读写含中文的txt文件时,经常会出现读出或写入的内容会出现乱码.原因其实很简单,就是系统的编码和程序的编码采用了不同的编码格式.通 ...

  2. java zip 压缩乱码_java实现zip压缩中文文件名乱码怎么办?

    java实现zip压缩中文文件名乱码怎么办? java实现zip压缩中文文件名乱码的解决办法: 一.文件压缩的中文乱码问题 1.中文文件名的乱码解决 对于压缩的文件,当文件名称是中文时,若使用JDK ...

  3. java 过滤器 中文_java中Filter过滤器解决中文乱码办法

    java中Filter过滤器解决中文乱码办法 发布时间:2020-04-07 10:19:09 来源:亿速云 阅读:16 作者:小新 这篇文章主要为大家详细介绍了java中Filter过滤器解决中文乱 ...

  4. php mysql中文乱码怎么解决_php读取mysql中文乱码怎么解决?

    解决方法:1.在网页文件中使用设置UTF-8编码:2.新建数据库时设置UTF-8编码:3.PHP连接数据库时,使用"mysql_query("set names 'utf8'&qu ...

  5. java 字节流乱码_java用字节流读取中文乱码怎么解决?

    首先,如果你明确的知道使用的编码,那么你可以在读取完毕生成字符串的时候直接指定编码. 例如: FileInputStream in = new FileInputStream("aaa.tx ...

  6. java 调用 dll 乱码_java调用c++ dll出现中文乱码

    最近的开发用到了使用java调用本机动态连接库的功能,将文件路径通过java调用C++代码对文件进行操作.在调用中如果路径中包含有中文字符就会出现问题,程序运行就会中止.下面用一个小例子,来说明记录下 ...

  7. java dll 乱码_java调用c++ dll出现中文乱码 | 学步园

    最近的开发用到了使用java调用本机动态连接库的功能,将文件路径通过java调用C++代码对文件进行操作.在调用中如果路径中包含有中文字符就会出现问题,程序运行就会中止.下面用一个小例子,来说明记录下 ...

  8. java通字乱码_Java解决通信过程的中文乱码的问题

    Java解决通信过程的中文乱码的问题 前言: Java的编程中,经常会碰到汉字的处里及显示的问题,比如一大堆乱码或问号. 这是因为JAVA中默认的编码方式是UNICODE,而中国人通常使用的文件和DB ...

  9. java中判断字符串乱码_java中如何判断字符串是否乱码

    java中如何判断字符串是否乱码 发布时间:2020-06-18 13:43:41 来源:亿速云 阅读:113 作者:鸽子 项目中有一个功能 在IE中GET方式提交会产生乱码 但有两个入口都会走这同一 ...

最新文章

  1. 如何把字符串类型转换成整型?
  2. 一种定位内存泄露的方法(Linux)
  3. Leetcode每日必刷题库第5题,如何实现最长回文子串?
  4. 《编码的奥秘》---学习编程一年半的体会
  5. linux之通过tail命令动态跟踪日志文件里面的末尾信息
  6. JUnit-4.12报java.lang.NoClassDefFoundError: org/hamcrest/SelfDescribing异常的解决
  7. RuoYi-Cloud 部署篇_01(linux环境 mysql+nginx版本)
  8. docker安装文档
  9. Pentium II Pentium III架构/微架构/流水线 (2) - P6详解 - 前端(指令预取/译码/动态分支预测静态分支预测)
  10. 169、多数元素(python)
  11. 关于shopex网店系统和网店助理的几点优化建议
  12. 计算机专业职业规划英语小作文,关于职业规划的英语作文
  13. 安装工程造价课程设计_安装工程造价课程设计心得体会及建议
  14. 34604-52-9,Ms-PEG3-Ms甲磺酸基是良好的离去基,也可用作伯醇的保护基
  15. SpringMvc导入Excel
  16. 这份整理的图解Java(全彩版)火了,完整PDF开放下载
  17. 日常水文章之Linux+arm+阿里IOT sdk+Cmake
  18. 手把手教你免费、批量转换HEIC图片到JPG
  19. WMS item与LPN的关系
  20. AI 靠眨眼反制假视频;马斯克等联名承诺不发展AI武器系统 | 一周 AI 新闻

热门文章

  1. php验证邮编,php 电话号码 手机号码 邮编 电子邮件 验证
  2. 2021年R2移动式压力容器充装复审考试及R2移动式压力容器充装证考试
  3. 使用 echarts实现中国地图
  4. 经纬财富:日照怎么正确的加仓
  5. EasyMock测试
  6. 扇区搜索机制的果蝇优化算法-附代码
  7. 《ZigBee开发笔记》第六部分 项目篇 基于ZigBee和Openwrt的智能家居控制系统(五)
  8. 培训教育系统阶段性效果展示
  9. 什么软件测试4g网络速度,4G网速有多快?4G网速亲身测试体验
  10. VICON视频会议产品价格