1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > RandomAccessFile类的readLine方法对文本文件中文字符读取显示乱码的问题及解决方法的深入分析

RandomAccessFile类的readLine方法对文本文件中文字符读取显示乱码的问题及解决方法的深入分析

时间:2022-11-09 04:59:56

相关推荐

RandomAccessFile类的readLine方法对文本文件中文字符读取显示乱码的问题及解决方法的深入分析

采用readLine方法对txt文本读取中文字符显示乱码,尽管很快找到解决方案,但疑惑反而更多。

1.问题

RandomAccessFile ran=new RandomAccessFile("D:/test.txt","r");System.out.println(ran.readLine());

当直接用readLine方法对txt文件里的中文字符读取时,显示出来的是乱码。

2.解决方案

经过查找,网上的解决方案是

System.out.println(new String(ran.readLine().getBytes("iso-8859-1"),"gbk"));

2.1.简单介绍下字符集(可跳过)

1、 ISO-8859-1

又称为西欧语言,在ascll码的基础上增加了96个字符和符号,单字节编码,无法表示中文。

2、GB2312/GBK/GB18030

GB2312:我国国家标准简体中文字符集,双字节编码。

GBK:汉字内码扩展规范,不属于国家标准,但囊括范围更广,兼容GB2312。

GB18030:国家标准,在GBK基础上再增加内容。(好像少见)

3、Unicode

计算机科学领域的业界标准,对世界上大部分的文字系统进行了整理、编码。

4、utf-8/utf-16

都是一种针对Unicode的可变长度字符编码。区别在于:

utf-8:对字符采用1到4字节编码。中文是3个字节。

utf-16:对大部分字符采用2字节编码,极少部分采用4字节编码。

2.2.接着解决方案

System.out.println(new String(ran.readLine().getBytes("iso-8859-1"),"gbk"));

解决方案的意思是:

(提下编码解码的概念:编码:把字符转换成字节。解码:把字节转换成字符。)

将readLine读取出来的字符串通过getBytes方法按iso-8859-1编码字节数组,然后再将字节数组按gbk解码,最后转换成字符串输出。

[.9.16更新]删除一些多余的解释,主要的原因在readLine()源码里。

2.3.readLine()源码

public final String readLine() throws IOException {StringBuffer input = new StringBuffer();int c = -1;boolean eol = false;while (!eol) {switch (c = read()) { //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();}

[.9.16更新]重写了对源码的解析,以前研究的不够透彻。

readLine方法通过read()方法读取文本文件里存储的字节。然后将int型的字节数据转换成char型,重点在这里。

char类型用2个字节的Unicode值表示一个字符,读取到的GBK编码单字节被添加了一个全零的字节组成了Unicode值。

而iso-8859-1是单字节编码,对这个Unicode值进行iso-8859-1编码将会去掉前面补充的零,得到原来GBK编码的字节,这时再用GBK解码即可得到原来的字符。

举个例子——

"你"字对应的GBK编码是0xC4E3(0x表示十六进制)read()方法读取到两个int类型的字节0xC4和0xE3,转变成char型:0x00C4,0x00E3如果直接输出,编译器会直接查找/计算0x00C4这个Unicode值对应的字符,很显然会输出乱码。采用iso-8859-1编码后:0xC4,0xE3采用GBK解码成Unicode值:0x4F60,为什么不是解码成字符?因为char或String类型存储的就是Unicode值,经过查找或计算就能得到相应的字符。如果不采用iso-8859-1编码直接GBK解码会怎么样?编译器将会对0x00C4,0x00E3进行GBK解码,因为GBK编码解码是两个字节对应一个字符的,所以会得到两个字符,这种情况也会导致乱码。

因为在写另一份更加详细的java字节流读取博客,所以对这篇博客的修改很粗糙,可能你看完有点点感觉但好像又没完全弄懂,可以看下这篇——Java字节流读取中文文本编码解码详解

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。