IO转换流 流的区别

  • 引入

           在对文件进行读写操作过程中,字节流可以操作所有数据,可是当我们操作的文件中有中文字符,并且需要对中文字符做出处理时,程序在读取含有中文的文件时,我们并没有看到具体的中文,而是看到一些数字,这是什么原因呢?既然看不到中文,那么我们如何对其中的中文做处理呢?要解决这个问题,我们必须研究下字符的编码过程。

       

          在IO开发过程中,我们传输最频繁的数据为字符,而以字节方式传输字符需要每次将字符串转换成字节再处理,而且也丧失了程序员对数据内容的判断(因为程序员只认识字符,不认识字节)。所以,为了让程序员方便对字符进行操作,Java提供了专门以字符作为操作单位的类——字符流,其底层仍然为字节流。

显然,字符流只能操作字符,无法操作其他数据,如声音、视频等。


  • 字符编码表     

        我们知道计算机底层数据存储的都是二进制数据,而我们生活中的各种各样的数据,如何才能和计算机中存储的二进制数据对应起来呢?

        把每一个字符和一个整数对应起来,就形成了一张编码表,编码表就是ASCII表。其中就是各种英文字符对应的编码。

编码表:其实就是生活中字符和计算机二进制的对应关系表。

1、ascii: 一个字节中的7位就可以表示。对应的字节都是正数。0-xxxxxxx

2、iso-8859-1:拉丁码表 latin,用了一个字节用的8位。1-xxxxxxx  负数。

3、GB2312:简体中文码表。包含6000-7000中文和符号。用两个字节表示。两个字节都是开头为1 ,两个字节都是负数。

          GBK:目前最常用的中文码表,2万的中文和符号。用两个字节表示,其中的一部分文字,第一个字节开头是1,第二字节开头是0

          GB18030:最新的中文码表,目前还没有正式使用。

4、unicode:国际标准码表:无论是什么文字,都用两个字节存储。

       Java中的char类型用的就是这个码表。char c = 'a';占两个字节。

       Java中的字符串是按照系统默认码表来解析的。简体中文版 字符串默认的码表是GBK。

5、UTF-8:基于unicode,一个字节就可以存储数据,不要用两个字节存储,而且这个码表更加的标准化,在每一个字节头加入了编码信息(后期到api中查找)。

能识别中文的码表:GBK、UTF-8;正因为识别中文码表不唯一,涉及到了编码解码问题。

对于我们开发而言;常见的编码 GBK  UTF-8  ISO-8859-1

文字--->(数字) :编码:就是看能看懂内容,转换成看不懂的内容。

(数字)--->文字  : 解码: 就是把看不懂的内容,转换成看懂的内容。


IO流的分类

|- 字节流

    |- 字节输入流 InputStream 抽象类

        |-  FileInputStream 操作文件的字节输入流

|- 字节输出流 OuputStream抽象类

    |-FileOutputStream 操作文件的字节输出流

|- 字符流

    |- 字符输入流 Reader抽象类

            |- FileReader 用来操作文件的字符输入流(简便的流)

    |- 字符输出流 Writer抽象类

            |- FileWriter 用来操作文件的字符输出流(简便的流)


  • 转换流

OutputStreamWriter流对象,它到底如何把字符转成字节输出的呢?

        其实在OutputStreamWriter流中维护自己的高效区,当我们调用OutputStreamWriter对象的write方法时,会拿着字符到指定的码表中进行查询,把查到的字符编码值转成字节数存放到OutputStreamWriter高效区中。然后再调用刷新功能,或者关闭流,或者高效区存满后会把高效区中的字节数据使用字节流写到指定的文件中。


  • InputStreamReader


注意:在读取指定的编码的文件时,一定要指定编码格式,否则就会发生解码错误,而发生乱码现象。


  • 转换流和子类区别

发现有如下继承关系:

Writer 字符输出流

|- OutputStreamWriter   转换流(字符流—>字节流)(属于字符输出流, 可以指定字符编码表,用来写入数据到文件)

                           |--FileWriter操作文件中字符输出流,采用默认的字符编码表

Reader 字符输入流

|- InputStreamReader: 转换流(字节流à字符流)(属于字符输入流,可以指定字符编码表,用来从文件中读数据)

|--FileReader操作文件中字符输入流,采用默认的字符编码表

父类和子类的功能有什么区别呢?

OutputStreamWriter和InputStreamReader是字符和字节的桥梁:也可以称之为字符转换流。字符转换流原理:字节流+编码表。

FileWriter和FileReader:作为子类,仅作为操作字符文件的便捷类存在。当操作的字符文件,使用的是默认编码表时可以不用父类,而直接用子类就完成操作了,简化了代码。

InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"));//默认字符集。

InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"),"GBK");//指定GBK字符集。

FileReader fr =new FileReader("a.txt");

这三句代码的功能是一样的,其中第三句最为便捷。

注意:一旦要指定其他编码时,绝对不能用子类,必须使用字符转换流。什么时候用子类呢?

条件:

1、操作的是文件。2、使用默认编码。

总结:

字节--->编码表--->字符 : 看不懂的--->看的懂的。  需要读。输入流。 InputStreamReader

字符--->编码表--->字节 : 看的懂的--->看不懂的。  需要写。输出流。 OutputStreamWriter

猜你喜欢

转载自blog.csdn.net/wzc1991520/article/details/80193730
今日推荐