Java读写文件之中文乱码(上)

时间:2022-06-26 10:34:24

这个问题还是上次博客提到的问题,当时问题虽然暂时找到了解决方法,但是总感觉不是很满意。


问题先描述一下:就是往一个文件里面写入一个JSONArray,后面就是往里面加入JSONObject,写入的方法不是累加,而是覆盖,就是每次(非第一次)写入的时候先读取文件,生成一个JSONArray,再put一个JSONObject后写入原先的文件,依次重复,里面的数据中英文都有。在文件的大小达到一定数量的时候,就概率发生中文乱码的情况,符号是一串“�”,或两个或三个或四个。

当时分析是线程异步操作与同一个文件造成的,比如在前一次写入还未完成的时候,下一次的读取已经开始。由于解决工作催的急,当时没想很多,就开始着手解决了,不是操作同一个文件的问题吗,行,那就不写在一个文件里面了,也就是每次写入的都是一个新文件,这个就可以避开上面读和写同时操作一个文件的情况了。

写完了测试,居然真的没有乱码的情况了,虽然文件是多了点,但是由于每个文件都很小,基本也不怎么影响效率,就交差了。


本来这个事情应该就这样过去了,可能哥有点完美主义,最近研究代码的时候,发现还有其他类型的文件也是按照以前的方式读写的,只是平时使用不多一直没有出现乱码的问题,怀着好奇的心理,做了一个小小的压力测试,妈蛋,果然也乱码了。这就意味着这个文件的读写都有隐患都要修改成上面的方法。

但是哥觉得有点不爽:1、这样修改的代码有点多(哥有点懒);2、修改后生成的文件数量实在有点多了(哥还有点强迫症)。

就想如果还是按照以前那样写在同一个文件里面,又不会出现乱码的话该多好,多漂亮。

接着就开始尝试其他的方法了,主要的方法如下:

1、既然是异步操作同一个文件引起的,行,哥就加同步锁,让你在读的时候就不能写,写的时候不能读;

2、既然是文件内容比较大的时候出现乱码,那就应该是读跟写都比较耗时,出现了同时访问的情况,行,哥就在写的时候不用覆盖,采用直接往后累加的方法,这样就不用在写之前读文件了。

想起来哥还是很佩服自己能想到这些好点子的,但是结果都有乱码,哥百思不得其解。


这下好了,没招了,又不想放弃,因为之前的解决方法想起来实在感觉有点恶心。无聊之下,把整个逻辑代码部分从头看了一遍,希望能找到点蛛丝马迹,结果还真发现了一点异样。

由于这个代码是之前的人留下的,所以有些代码风格跟哥有点不同,比如,在读文件的时候,他用的是FileInpuStream类,而哥习惯用BufferReader。看不顺眼,哥就给改成自己习惯的方式了,结果运行测试后乱码消失了。有点神来之笔。


本来准备研究一下到底发生了什么的,没想被叫去开了个长会,回来后研究了一下,应该是这么个情况:

1、FileInputStream类是按字节读取的,BufferReader类是按字符读取的,一个英文字母是一个字节,一个汉字是两个字节或一个字符,而之前是按1024字节一次读取的,如果第1023个字节恰好是个字母,而后面跟着一个汉字,那第1024个字节应该读取的是什么,半个汉字?

2、BufferReader如果是按字符读取,其实也会发生这种情况,但是我按照习惯写的readLine,按行读取的,是不是这样就避免了这种读半个字的情况?


所以,最终的原因还得明天去办公室证明一下,经得起检验的才是真理,至于为什么去办公室,因为重新写个测试的demo太麻烦了,哥确实有点懒。