Java学习笔记(二十一):IO流之字符流

由于字节流操作中文不是特别方便,所以java就提供了字符流。字符流 = 字节流 + 编码表。

一、编解码

编码就是把字符串转换成字节数组,方法如下:

public byte[] getBytes();使用平台的默认字符集将此 String编码为 byte 序列,并将结果存储到一个新的 byte 数组中。 

public byte[] getBytes(String charsetName) 使用指定的字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。

String str="我爱你";
//按照平台默认的码表进行编码
byte[] bytes = str.getBytes(); //编码

//按照GBK来变得码
byte[] gbks = str.getBytes("UTF-8");

二、解码

解码就是把字节数组转换成字符串,方法如下:

public String(byte[] bytes):	通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String。

public String(byte[] bytes, String charsetName) 通过使用指定的 charset 解码指定的 byte 数组,构造一个新的 String。

//按照平台默认的码表进行解码
String s = new String(bytes);

//按照GBK来解码:
String s1 = new String(gbks, "GBK");

转换流OutputStreamWriter

OutputStreamWriter 是字符流通向字节流的桥梁,可使用指定的码表 将要写入流中的字符编码成字节。
它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。

构造方法:

OutputStreamWriter(OutputStream out):根据默认编码(GBK)把字节流的数据转换为字符流
	//输出流所关联的文件,如果不存在会自动创建
    OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream("a.txt"));

	OutputStreamWriter(OutputStream out,String charsetName):根据指定编码把字节流数据转换为字符流
	//可以指定码表
    OutputStreamWriter out2 = new OutputStreamWriter(new FileOutputStream("a.txt"),"GBK");

写数据的方法如下,注意:使用OutputStreamWriter写入数据一定要刷新才会显示。

public void write(int c) 写一个字符
	
	public void write(char[] cbuf) 写一个字符数组
	
	public void write(char[] cbuf,int off,int len) 写一个字符数组的 一部分
	
	public void write(String str) 写一个字符串
	
	public void write(String str,int off,int len) 写一个字符串的一部分

追加写入和异常捕获

OutputStreamWriter同FileOutputStream,每次写入的编译都会重新覆盖文件的内容。要想每次写入追加内容,也就是每次编译不仅保存原数据,同时写入新数据,就需要进行追加写入操作。因为异常捕获的方法同FileOutputStream,因此一同展示。

public static void main(String[] args) {
        //流的异常处理
        OutputStreamWriter out = null;
        try {
        //追加处理的方式是在FileOutputStream中添加true
            out = new OutputStreamWriter(new FileOutputStream("c.txt", true));
            out.write("你看乱码了没有");
            out.write("\r\n");
            out.write('好');
            out.write("\r\n");
            //一次写入一个字符数组
            out.write(new char[]{'a', 'b', 'c', '哈', '哈'});
            out.write("\r\n");
            //一次写入字符串的一部分 从字符串的2索引出开始,写3个字符
            out.write("写入字符串的一部分", 2, 3);
            out.write("\r\n");
            //一次写入字符数组的一部分,从0索引处开始 写3个字符
            out.write(new char[]{'a', 'b', 'c', '哈', '哈'}, 0, 3);
            out.write("\r\n");
            //字符流,记得要刷新
            out.flush();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //释放资源
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

转换流InputStreamReader

InputStreamReader 是字节流通向字符流的桥梁,它使用指定的 码表 读取字节并将其解码为字符。
它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。

构造方法:

InputStreamReader(InputStream is):用默认的编码(GBK)读取数据
//输入流所关联的文件,如果不存在就报错
InputStreamReader in = new InputStreamReader(new FileInputStream("e.txt"));

InputStreamReader(InputStream is,String charsetName):用指定的编码读取数据
//指定码表
InputStreamReader in2 = new InputStreamReader(new FileInputStream("e.txt"), "GBK");

读数据方法:

public int read() :一次读取一个字符
	
public int read(char[] cbuf) :一次读取一个字符数组 如果没有读到 返回-1

字符流复制文本文件

public static void main(String[] args) throws IOException {
        //使用字符流来复制文本文件
        InputStreamReader reader = new InputStreamReader(new FileInputStream("MyTest.java"));
        OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream("C:\\Users\\Desktop\\bbb.java"));
        //一次读取一个字符,写一个字符。来复制文件,效率低 不推荐
        //推荐一次读写一个字符数组来复制
        char[] chars = new char[2000]; //定义一个字符数组,充当缓冲区
        int len=0;//用来记录实际读取到的字符个数
        int count=1;
        while ((len=reader.read(chars))!=-1){
            System.out.println("循环次数"+(count++));
            writer.write(chars,0,len);
            writer.flush();
        }
        reader.close();
        writer.close();
        System.out.println("复制完成");
    }

FileWriter和FileReader

转换流的名字比较长,而我们常见的操作都是按照本地默认编码实现的,所以为了简化我们的书写,转换流提供了对应的子类FileWriter和FileReader。其使用方法大致与InputStreamReader和OutputStreamWriter完全一致,但是也有需要注意的地方:

  1. FileReader和FileWriter的构造方法与其父类InputStreamReader和OutputStreamWriter不同,FileReader和FileWriter构造方法中的参数可以是File类型和String类型,而不是其父类要求的字节流;
  2. FileReader和FileWriter用于写入字符流。要写入原始字节流,就需要使用 FileOutputStream和FileInputStream。

高效字符流

高效字符流有以下两种:

  • BufferedWriter:用于写出数据 ,是高效的字符输出流;
  • BufferedReader:用于读取数据 ,是高效的字符输入流。
    构造方法:
BufferedWriter:
public BufferedWriter(Writer w)

BufferedReader:
public BufferedReader(Reader e)

字符缓冲流中提供了以下两个特殊方法:

BufferedWriter:	public void newLine():根据系统来决定换行符,是具有系统兼容性的换行符。
	
	BufferedReader:	public String readLine():一次读取一行数据。以换行符为标记,读到换行符就换行,没读到数据返回null。包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null。

具体使用方法在使用字符缓冲流复制文本文件中体现:

public static void main(String[] args) throws IOException {
        //使用高效的字符流。读取一行,写入一行来复制文件,逐行复制。
        BufferedReader reader = new BufferedReader(new FileReader("MyTest.java"));
        BufferedWriter writer = new BufferedWriter(new FileWriter("hehe.java"));
        //循环的进行读取一行,写入一行
        //一行一行读取,读取不到返回的是null
        String line=null; //定义一个变量,来记录每次读取到的一行文本
        while ((line=reader.readLine())!=null){
            writer.write(line);
            //writer.write("\r\n");
            writer.newLine();
            writer.flush();
        }
        writer.close();
        reader.close();
    }