NIO 文件乱码问题解决

来源:互联网 发布:windows lua环境变量 编辑:程序博客网 时间:2024/06/08 16:41

造成NIO乱码的问题是因为读取的信息是按照特定编码读取的字节流信息,读取的时候受到读取限定,就有可能出现读取的不是一个完整的字节数组信息。
例如: 你好啊 。

在UTF-8的字节数组是[-28,-67,-96,-27,-91,-67,-27,-107,-118]。在GBK的字节数组是[-60,-29,-70,-61,-80,-95]。在unicode中数值是 20320,22909,21834。

转码就需要完整的字节信息,utf-8中[-28,-67,-96]代表 你 ,如果读取字节流信息的时候制度去到[-28]或者[-28,-67]这种不完整的编码,那么转码成unicode就会变成乱码。因此解决乱码就是需要我们将多读取的字节信息截留,下次完整读取。
以下是针对utf-8 与GBK文件的解决代码,其他编码没有测试过。

import java.io.RandomAccessFile;import java.nio.ByteBuffer;import java.nio.CharBuffer;import java.nio.channels.FileChannel;import java.nio.charset.Charset;import java.nio.charset.CharsetDecoder;public class Test {    public static void main(String[] args) {                //GBK文件 使用 GBK编码        new Test().readFile("C:\\Users\\Administrator\\Desktop\\1.txt", "UTF-8");    }    public void readFile(String path, String charsetName) {        Charset c = Charset.forName(charsetName);        // 解码器,字节流信息转换为字符信息        CharsetDecoder decoder = c.newDecoder();        try (RandomAccessFile raf = new RandomAccessFile(path, "r"); FileChannel fc = raf.getChannel();) {            // 设置成5是因为不管是UTF-8还是GBK在全中文文档都会出字节信息被截取的情况,也就是所谓会出现乱码。            //这样方便测试            ByteBuffer bytes = ByteBuffer.allocate(5);            CharBuffer cb = CharBuffer.allocate(5);            int size = fc.read(bytes);            while (size != -1) {                bytes.flip();                //size<5,小于5的时候说明文件已经读取结束了                //为了防止源文件就是一个破损的文件,末尾有不符合规范的字节流                //当末尾的时候就不做截留操作,直接转码                decoder.decode(bytes, cb, size<5);                cb.flip();                System.out.print(cb.toString());                //全中文文档第一次读取的时候,五个字节就是说UTF-8和GBK的文档都会有一个字节信息未被读取                //这个时候需要保存多读取的信息,UTF-8sub=2,后面两个属于非正常字节信息                //GBK的时候sub=1 只有一个非正常的自己信息                               //后面继续读取的时候将会根据实际情况进行截留                int sub = bytes.limit()-bytes.position();                bytes.clear();                cb.clear();                //将读取的定位值 减去多读取的信息                fc.position(fc.position()-sub);                size = fc.read(bytes);            }        } catch (Exception e) {            e.printStackTrace();        }    }}
原创粉丝点击