Java之IO(三)转换流:Writer/Reader接口

2018-08-27  本文已影响0人  如果仲有听日

1. 编码表

常见编码表:GBK,utf-8

编码:文字字串-》数字字节流:"string text".getBytes ----> byte[] bArr

解码:数字字节流-》文字字串:byte[] bArr ----> new String(bArr)

查看linux系统默认编码格式

2. FileWriter、FileReader类

2.1 FileWriter类

超类:java.io.Writer 接口,需要重写Writer中的抽象方法

局限:只能写文本文件,只能写字符流,且write()之后需要flush()字符缓冲

            不能修改其编码格式,只能是默认的GBK编码方式

好处:提供了写入String的write()重载方法,写入中文非常方便

write重载方法:

    void write(int c)

    void write(char[] charBuf)

    void write(char[] cbuf, int off, int len)

    void write(String str)

public static void fWriterDemo() throws IOException{

    FileWriter fw = new FileWriter("/kluter/temp/fw.txt");

    fw.write(110);

    fw.write(0x0d);

    fw.write(0x0a);

    fw.flush();

    char[] cArr = {'a', 'B', 'c', 'D', 'e', '\n'};

    fw.write(cArr);

    fw.flush();

    fw.write(cArr, 2, 3);

    fw.flush();

    fw.write("Test String\n");

    fw.flush();

    fw.close();

}

特别注意,字符输出流写入文件需要做flush()

2.2 FileReader

超类:java.io.Reader 接口,需要重写Reader中的抽象方法

局限:只能读取文本文件,只能读字符流,且read()之后需要

没有String的都区功能,对文本的字符读取无法界定

不能修改其编码格式,只能是默认的GBK编码方式

好处:读取中文非常方便

read()重载方法:

    int read() 读一个字符

    int read(char[] charBuf)

    int read(char[] cbuf, int off, int len)

public static void fReaderDemo() throws IOException{

    FileReader fr = new FileReader("/kluter/temp/fw.txt");

    int ret = 0;

    // while((ret = fr.read()) != -1){

    // out.print((char)ret);

    // }

    // out.print("**************************");

    //

    // fr.reset();

    ret = 0;

    char[] cbuf = new char[10];

    String s = null;

    while((ret = fr.read(cbuf)) != -1){

        s = new String(cbuf, 0, ret);

        out.print(s);

    }

    fr.close();

}

2.3 用FileWriter、FilerReader类实现文本文件拷贝

略,参考:https://www.jianshu.com/p/bf3fb779b742 中的3.2

用buffer的形式拷贝效率高,也需要考虑IOexception

2.4 flush() 与 close()的区别

flush和close方法都有立即将字符写入文件的功能,区别是:

flush()之后还可以继续write(),而close则不行

3. OutputStreamWriter、InputStreamReader

由于InputStream和OutputStream体系中的类,以及FileWriter和FileReader都是处理字符的

现在引入两个新的类来处理字符转换为字节,用于不同编码间的转换

3.1 OutputStreamWriter

转换流

    java.io.OutputStreamWriter 继承Writer接口

    就是一个字符输出流,写文本文件

    write()重载方法,同样有字符参数、字符数组、以及字符串

    字符流通向字节流的桥梁,可以将字符流转字节流:

         (我试过可以用FileWriter写中文、韩语等也能成功,最开始不清楚为什么这里要做转换。最后发现FileWriter是OutputStreamWriter的子类,FileWriter更简单,但是不能改变编码表(只能用系统默认的),例如字符是中文的时候,编码表用GBK更节约空间,GBK是2个字节存储的,而FileWriter在英文linux上默认使用utf-8是3个字节存储的)

        例如中文的“你好”转换为utf-8,“你好是字符”,需要转换为gbk的2x5字节。OutputStreamWriter的作用就是将“你好”字符去查询编码表(例如可以查询utf8、GBK等等)转换成字节形式(utf8、GBK表示),之后再用字节输出流(目前只学过FileOutputStream)将转换后的字节写入文件


3.1.1 构造方法

OutputStreamWriter(OutputStream out) 

        //接口的多态应用,接收所有字节输出流

OutputStreamWriter(OutputStream out, Charset cs) 

        //不常用

OutputStreamWriter(OutputStream out, CharsetEncoder enc)

        //不常用

OutputStreamWriter(OutputStream out, String charsetName) 

        //charsetName常见有:GBK、utf-8,大小写不限

3.1.2 用OutputStreamWriter写字符到文件

这里说明代码中三处地方:

    ①:构造方法如果不填编码格式,则为该系统的默认编码格式,在英文linux上默认是utf-8

    如果填写了编码格式,大小写不敏感

    ②:写入的字符来决定采用哪种编码格式,如果只有中文,则用GBK(2个字节表示一个汉字)能节约更多空间

    如果有多种语言,则utf-8能全部涵盖

    ③:这里只需要close外层的OutputStreamWriter的对象,内层的FileOutputStream也就自动关闭了

    ④:这段测试代码的含义是将字符“你好是字符”去查询gbk编码表后转换成字节表示,在用FileOutputStream以字符流的形式一个字节一个字节写入文件

3.2 InputstreamReader

这个类的原理和使用方式和3.1中的OutputStreamWriter刚好是相反的

java.io.InputStreamReader 继承Reader

字符输入流,读取文本文件,将字节流转字符流

读取方法

    read()重载方法,能够读取1个字符,也可以读取字符数组

使用默认utf-8格式读取gbk文件,打印显示乱码 使用给定gbk编码格式读取gbk文件,打印显示中文

说明:

① InputStreamReader构造方法也有单参和双参,当不填编码格式时,采用系统的默认编码格式;如果填写的编码格式,则会按照编码格式来识别FileInputStream读取到的字节

②这里可以一个字节一个字节读取,也可以多个字节读取,多个字节的读取形式效率更高

③只需要close外层InputStreamReader的对象,内层有系统close

3.3 转换流父类、子类的关系

OutputStreamWriter的子类FileWriter

InputStreamReader的子类FileReader

    在使用时,如果都用默认的编码格式,则采用子类

    如果需要转换编码格式,则必须用父类

上一篇下一篇

猜你喜欢

热点阅读