Java的字节流读取中文乱码问题

1、万物皆字节

  一切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存,都一个一个的字节,那么传输时一 样如此。所以,字节流可以传输任意文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底层传输的始终为二进制数据。就是汉子也不例外,在存储时也是一个个的字节。既然都是字节,为什么还会产生乱码呢?

2、字节和字符

字节: 一个字节(byte)等于八个位(bit),相当于八个开关。
字符: Java规定了字符的内码要用UTF-16编码,所以1个字符=2个字节。但我们通常采用UTF-8的编码格式,UTF-8编码是变长编码,通常汉字占三个字节,扩展B区以后的汉字占四个字节。由于UTF-8特点的编码方式,读取文件时可以判断一个字符占多少字节,从而保证数据的读取完整。因此,一个字符等于多少字节,是由编码方式决定的。
  重点来了,系统在读取文件时,是怎么判断多少字节是一个字符呢?请看下图!系统在从开头扫描字节,从开端的0-1数字就能判断这个字要读取多少字节。
  所以就得出了结论,使用字节流操作中文不一定会乱码!只是看你处理的方式!
在这里插入图片描述

3、何时不会乱码 – 写完再读

  当你以字节流方式读取一个文件时,不间断地写入一个文件,此时就不会乱码。因为你只是将一串0-1数字复制进另一个文件,并不涉及中途读取的情况,等你把所有的中文的字节流写进去,此时系统读取仍会转化为一个一个的汉字。

准备工作:

import java.io.File;
import java.io.FileOutputStream;
/**
 * @author RuiMing Lin
 * @date 2020-03-13 22:09
 */
public class Demo3 {
    public static void main(String[] args) throws Exception{
        File fis = new File("fis.txt");
        fis.createNewFile();    // 创建一个空文件 fis.txt
        File fos = new File("fos.txt");
        fos.createNewFile();    // 创建一个空文件 fos.txt
        FileOutputStream fileOutputStream = new FileOutputStream(fis);
        fileOutputStream.write("我爱你,中国!".getBytes());   // 向fis.txt写入 “我爱你,中国”
        fileOutputStream.close();
    }
}

写入fos.txt文件:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
/**
 * @author RuiMing Lin
 * @date 2020-03-13 22:09
 */
public class Demo3 {
    public static void main(String[] args) throws Exception{
        FileInputStream fileInputStream = new FileInputStream("fis.txt");
        FileOutputStream fileOutputStream = new FileOutputStream("fos.txt");
        int len;
        while ((len = fileInputStream.read())!= -1){    
            fileOutputStream.write(len);    // 一次写入一个字节,或者一次写入多个字节也可以
        }
        fileInputStream.close();
        fileOutputStream.close();
    }
}

结果输出:
在这里插入图片描述

4、何时会乱码 – 边写边读

当你以字节流边读取边使用的话,就很有可能发生乱码!

import java.io.FileInputStream;
/**
 * @author RuiMing Lin
 * @date 2020-03-13 22:21
 */
public class Demo4 {
    public static void main(String[] args) throws Exception{
        FileInputStream fileInputStream = new FileInputStream("fis.txt");
        int len;
        byte[] bytes = new byte[3];     //假设一个汉字占3个字节
        while ((len = fileInputStream.read(bytes)) != -1){
            System.out.print(new String(bytes,"utf-8"));    //使用print,不进行换行
        }
        fileInputStream.close();
    }
}

结果输出:

我爱你,中国!

  咋一看好像不会乱码!这是因为“我爱你,中国!”中每一个字和标点符号都是三个字节的,因此不会乱码!
  当我们把“我爱你,中国!”改为“China,我爱你!”,看看此时的结果:
在这里插入图片描述

5、字符流为什么不会乱码

  从上面的utf-8编码方式可以知道,字符流读取一串0-1数字时,会根据前面几位判断要读取几个字节,当发现时1110**** 10****** 10******时,就会读取3个字节就立马刹住不读取,此时读取内容为一个汉字。

有错误的地方敬请指出!觉得写得可以的话麻烦给个赞!欢迎大家评论区或者私信交流!

发布了30 篇原创文章 · 获赞 72 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Orange_minger/article/details/104850611