美文网首页
Java字节流 字符流(三)

Java字节流 字符流(三)

作者: 哪个旮旯的 | 来源:发表于2020-04-22 10:17 被阅读0次

其实,一切都是字节流,没有字符流这个东西。字符只是根据编码集对字节流翻译之后的产物。

代码分析

看下面这段代码:

 public class JavaEncode {

    public static void main(String[] args) throws IOException {
        
       // test 1
        InputStream inputStream = new FileInputStream(new File("demo.txt"));
        byte[] bytes = new byte[6];
        inputStream.read(bytes);
        System.out.println(HexUtil.encodeHex(bytes));

        String utf8Str = new String(bytes, "gbk");
        System.out.println(utf8Str);

       // test 2
        inputStream = new FileInputStream(new File("demo.txt"));
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "GBK");
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
        String cs = bufferedReader.readLine();
        System.out.println(cs);

    }
}

其中demo.txt中存储的文本为:


image.png

另外文件编码格式是UTF-8。

输出的结果为:

e4b8ade59bbd
涓浗
涓浗

其中e4b8ade59bbd为“中国”两个汉字的UTF-8编码,第二行和第三行为乱码,两次输出的乱码是一样的。

对于test 1

  • 首先创建了一个demo.txt文件的输入流(类似于一个管道)
  • 然后从输入流中读取文件的字节流。根据输出的结果,可以看出,test 1是以UTF-8编码格式,将“中国”两个汉字的字节读入字节数组的
  • 【String utf8Str = new String(bytes, "gbk");】debug一下,看看utf8Str中存的字符数组是什么



    它想将字符以UTF-8编码格式获取的字节数组再以GBK编码的形式转化为字符。
    GBK是定长编码,UTF-8是不定长编码,这一转肯定是要出问题的。“中国”两个字符以UTF-8编码,是长度为6的字节数组,GBK字符字节长度为2,所以变成了三个字符,但是在JVM中,都是Unicode字符编码来表示字符的,所以JVM又将三个GBK字符编码转换成了Unicode编码,存在JVM内存中,才有了utf8Str上图中的情况。

对于test 2,

  • 【 inputStream = new FileInputStream(new File("demo.txt"));】建立字节输入流
  • 【 InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "GBK");】InputStreamReader是字节流向字符流转换的桥梁,可以指定编码格式。
  • 【 BufferedReader bufferedReader = new BufferedReader(inputStreamReader);】 BufferedReader是字符流的一种实现方式,后面会介绍。
  • 【String cs = bufferedReader.readLine();】按行读取文本。字符串cs中的字符数组存储的是什么呢?


    image.png

    这行代码在读取文本中的信息的时候,应该也是经历了如下步骤

  1. 获取UTF-8编码格式字节数组 bs
  2. 根据GBK编码,将bs转化为GBK字符
  3. 将GBK字符转化为其对应的Unicode编码,于是有了上图cs的情况。

从上面的两个test可以看出, test 1可以操作到字节级别,这个就叫做字节流,test 2操作最小的也是一个Unicode字符,这个叫做字符流。从我们创建字符流对象的过程,可以知道,字符流其实是对字节流的封装,只不过字符流一次会操作一个Unicode字符。
另外,字节流处理的范围更加大,例如图片、音频等,我们可以获取他们的字节流,但是它们有自己的编码规则,无法转化为我们的字符。

Java I/O编码系统

  • 面向字节流的InputStream和OutputStream
  • 面向字符流的Reader 和 Writer

字节流的InputStream和OutputStream是一切的基础,实际总线中流动的只有字节流。Java中负责从字节流向字符流解码的桥梁是:
InputStreamReader和OutputStreamWriter,可以指定以什么编码格式读取或写入。

Java中的字符流处理的最基本的单元是Unicode码元(大小2字节),它通常用来处理文本数据。所谓Unicode码元,也就是一个Unicode代码单元,范围是0x0000~0xFFFF。在以上范围内的每个数字都与一个字符相对应,Java中的String类型默认就把字符以Unicode规则编码而后存储在内存中。然而与存储在内存中不同,存储在磁盘上的数据通常有着各种各样的编码方式。使用不同的编码方式,相同的字符会有不同的二进制表示。实际上字符流是这样工作的:

  • 输出字符流:把要写入文件的字符序列(实际上是Unicode码元序列)转为指定编码方式下的字节序列(OutputStreamWriter指定的编码,如果没有指定,则按照操作系统默认),然后再写入到文件中;
  • 输入字符流:把要读取的字节序列按指定编码方式解码为相应字符序列(按照InputStreamReader指定的编码,先编码,再转码为Unicode码元序列)从而可以存在JVM内存中。

相关文章

  • Java IO 流学习总结

    Java流操作有关的类或接口 Java流类图结构: 字符流和字节流 字符流的由来: 因为数据编码的不同,而有了对字...

  • IO Stream - 字符流

    字符流 字符流出现的原因1.字符流介绍:由于字节流操作中文不是特别方便,所以Java提供了字符流字符流 = 字节流...

  • Java 中字节流与字符流的区别?

    Java 中字节流与字符流的区别? 知乎高赞回答。参考:Java 中字节流与字符流的区别?[https://www...

  • 2020-07-03字符流

    为什么会出现字符流?由于字节流操作中文不是特别的方便,所以Java就提供了字符流(字符流 = 字节流+编码表) 用...

  • Java IO流的使用

    下面部分内容是参考Oubo的博客——Java IO流学习总结 Java流操作有关的类或者接口: 字符流和字节流 字...

  • No.16 转换流InputStreamReader/Outpu

    简介 在java.io除了字节流/字符流之外,还存在一组字节流-字符流的转换类。1.OutputStreamWri...

  • Java基础之IO流

    1.IO流 Java中有几种类型的流 答:字节流,字符流。字节流继承于InputStream、OutputStre...

  • 5-Java IO-装饰模式

    1.Java IO分类节点流-过滤流输入流-输出流字节流-字符流 2.InputStream,节点输入字节流的祖宗...

  • java io之字节流

    java的IO流按照流向可分为输入流、输出流 按照处理方式 字节流、字符流本文主要记载字节流 字节流 inpu...

  • Android面试之Java基础笔试题

    Java IO流 按照数据流的方向不同可以分为:输入流和输出流。 按照处理数据单位不同可以分为:字节流和字符流。字...

网友评论

      本文标题:Java字节流 字符流(三)

      本文链接:https://www.haomeiwen.com/subject/veuvbhtx.html