欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

J07-Java IO流总结七 《 InputStreamReader和OutputStreamWriter 》

程序员文章站 2022-10-16 16:02:52
前面在介绍FileReader和FileWriter的时候有说到,FileReader的读取字符功能,以及FileWriter的写出字符的功能,都不是它们自己实现的,而是,它们分别继承了InputStreamReader和OuputStreamWriter这两个转换流,利用这两个转换流,实现了字节数 ......

  

  前面在介绍filereader和filewriter的时候有说到,filereader的读取字符功能,以及filewriter的写出字符的功能,都不是它们自己实现的,而是,它们分别继承了inputstreamreader和ouputstreamwriter这两个转换流,利用这两个转换流,实现了字节数据与字符数据之间的转换,关于这点可以通过filereader和filewriter的源码看出来。

  下面将介绍这两个转换流,并分别通过几个简单的应用场景来熟悉它们的用法。

 

1. inputstreamreader

1.1  概念介绍

  inputstreamreader将底层的字节数据转换为字符数据,可以显式的或者使用平台默认的字符集进行转换。所有的字符流的转换工作都依赖于它来完成。

  根据api文档的描述,inputstreamreader 是字节流通向字符流的桥梁,它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。

每次调用 inputstreamreader 中的一个 read() 方法都会导致从底层输入流读取一个或多个字节。要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。

  为了达到最高效率,可要考虑在 bufferedreader 内包装 inputstreamreader。例如:

bufferedreader in
   = new bufferedreader(new inputstreamreader(system.in));

 关于源码:

  inputstreamreader的源码比较简单,它有一个非常重要的成员变量:

private final streamdecoder sd;

   inputstreamreader的主要实现都调用了这个流解码类streamdecoder,它只有这一个成员变量,而这一个类把它的所有操作都包括了。streamdecoder的主要作用是获取一个字节输入流inputstream,然后根据给定的编码方案读取字符,如果没有给定,则默认是系统编码。

  由源码可知,inputstreamreader的设计使用到了装饰设计模式,它本身并没有提供啥功能,具体的实现其实都由streamdecoder来实现了。

  源码中关于inputstreamreader的几个构造方法需要格外注意一下,因为通过它的构造方法,可以显式的指定解码所需的字符集:

J07-Java IO流总结七 《 InputStreamReader和OutputStreamWriter 》

 

 

1.2  应用示例

   system.in是字节流对象,代表键盘的输入,如果我们想按行接收用户的输入时,就必须用到缓冲字符流bufferedreader特有的方法readline(),但是经过观察会发现在创建bufferedreader的构造方法的参数必须是一个reader对象,如下:

public bufferedreader(reader in)

 这时候我们的转换流inputstreamreader就派上用场了。

 示例代码如下所示:

import java.io.bufferedreader;
import java.io.ioexception;
import java.io.inputstreamreader;

public class inputstreamreadertest {
    public static void main(string[] args) {
        bufferedreader br = null;
        
        string str = null;
        try {
            br = new bufferedreader(new inputstreamreader(system.in));
            while(!"exit".equals(str = br.readline())) {
                system.out.println(str);
            }
        } catch (ioexception e) {
            e.printstacktrace();
        }
    }
}

  代码运行效果:

 J07-Java IO流总结七 《 InputStreamReader和OutputStreamWriter 》

 

 

 

 

2.  outputstreamwriter

2.1  概念介绍

  outputstreamwriter是将字符数据转换为字节数据的流。可以显式的或者使用平台默认的字符集进行转换。所有的字符输出流的转换工作都依赖于它来完成

  根据api文档的描述,outputstreamwriter 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。

  每次调用 write() 方法都会导致在给定字符(或字符集)上调用编码转换器。在写入底层输出流之前,得到的这些字节将在缓冲区中累积。可以指定此缓冲区的大小,不过,默认的缓冲区对多数用途来说已足够大。注意,传递给 write() 方法的字符没有缓冲。

  为了获得最高效率,可考虑将 outputstreamwriter 包装到 bufferedwriter 中,以避免频繁调用转换器。例如:

writer out
   = new bufferedwriter(new outputstreamwriter(system.out));

 源码:

  阅读outputstreamwriter的源码,可以发现它跟inputstreamreader一样使用了装饰器模式,在它的类当中,持有了一个的引用streamencoder的应用,streamencoder可以理解为一个编码器,当调用outputstreamwriter的write、close方法时,实际上底层调用的还是这个streamencoder的方法。

  需要留意一下outputstreamwriter的构造方法:

J07-Java IO流总结七 《 InputStreamReader和OutputStreamWriter 》

 

 

2.2  应用示例

   system.out是字节流对象,代表输出到显示器,在上面的示例中按行读取用户的输入后,并且要将读取的一行字符串直接显示到控制台,就需要用到字符流的write(string str)方法,所以我们要使用outputstreamwriter将字符流转化为字节流。

示例代码如下所示:

import java.io.bufferedreader;
import java.io.bufferedwriter;
import java.io.ioexception;
import java.io.inputstreamreader;
import java.io.outputstreamwriter;

public class convertstreamtest {
    public static void main(string[] args) {
        bufferedreader br = null;
        bufferedwriter bw = null;
        
        string str = null;
        try {
            br = new bufferedreader(new inputstreamreader(system.in));
            bw = new bufferedwriter(new outputstreamwriter(system.out));
            
            while(!"bye".equals(str = br.readline())) {
                bw.write("-->" + str);
                bw.newline();
                bw.flush();
            }
        } catch (ioexception e) {
            e.printstacktrace();
        }
    }
}

  代码运行效果:

 J07-Java IO流总结七 《 InputStreamReader和OutputStreamWriter 》

 

 

 

3 转换流综合应用示例

  下面的示例代码中定义了两个方法,分别为utf8togbk()和gbktoutf8(),其中,utf8togbk()实现了从一个用utf-8编码的源文件复制数据到一个用gbk编码的目标文件,gbktoutf8()方法则正好反之。

 示例代码:

import java.io.bufferedreader;
import java.io.bufferedwriter;
import java.io.fileinputstream;
import java.io.filenotfoundexception;
import java.io.fileoutputstream;
import java.io.filereader;
import java.io.filewriter;
import java.io.ioexception;
import java.io.inputstreamreader;
import java.io.outputstreamwriter;
import java.io.unsupportedencodingexception;

public class converttest {
    public static void main(string[] args) {
//      gbktoutf8();
        utf8togbk();

    }

    ////////////////////////////////////////////////////////////
    private static void utf8togbk() {
        bufferedreader br = null;
        bufferedwriter bw = null;
        
        try {
            br = new bufferedreader(new inputstreamreader(new fileinputstream("./src/res/2_copy.txt"), "utf-8"));
            bw = new bufferedwriter(new filewriter("./src/res/2.txt"));
//            bw = new bufferedwriter(new outputstreamwriter(new fileoutputstream("./src/res/2.txt")));
            
            string str = null;
            while(null != (str = br.readline())) {
                bw.write(str);
                bw.newline();
            }
            
            
        } catch (filenotfoundexception e) {
            e.printstacktrace();
        } catch (unsupportedencodingexception e) {
            e.printstacktrace();
        } catch (ioexception e) {
            e.printstacktrace();
        } finally {
            if(null != bw) {
                try {
                    bw.close();
                } catch (ioexception e) {
                    e.printstacktrace();
                }
            }
            if(null != br) {
                try {
                    br.close();
                } catch (ioexception e) {
                    e.printstacktrace();
                }
            }
        }
    }
    
    ////////////////////////////////////////////////////////////
    private static void gbktoutf8() {
        bufferedreader br = null;
        bufferedwriter bw = null;
        
        try {
            br = new bufferedreader(new filereader("./src/res/2.txt"));
//          br = new bufferedreader(new inputstreamreader(new fileinputstream("./src/res/2.txt")));//使用默认字符集

            bw = new bufferedwriter(new outputstreamwriter(new fileoutputstream("./src/res/2_copy.txt"), "utf-8"));
            
            string str = null;
            while(null != (str = br.readline())) {
                bw.write(str);
                bw.newline();
            }
            
        } catch (filenotfoundexception e) {
            e.printstacktrace();
        } catch (unsupportedencodingexception e) {
            e.printstacktrace();
        } catch (ioexception e) {
            e.printstacktrace();
        } finally {
            if(null != bw) {
                try {
                    bw.close();
                } catch (ioexception e) {
                    e.printstacktrace();
                }
            }
            if(null != br) {
                try {
                    br.close();
                } catch (ioexception e) {
                    e.printstacktrace();
                }
            }
        }
    }
}