Java IO流详解(四)——字符流Reader和Writer

    前面一章介绍了字节流的使用,提到了字节流在处理utf-8编码的中文可能会出现乱码的情况(其他编码的中文同样会出现乱码),所以Java针对这一情况提供了字符流。

    但是字符流只能处理字符,不能用来处理 .jpg;.mp3;.mp4;.avi;.doc;.ppt等二进制文件,这些只能通过字节流来处理。所以对于纯文本的文件,强烈推荐使用字符输入输出流。

    字符流的本质其实就是基于字节流在读取时去查了指定的码表。


1、字符输入流Reader

    Reader是所有字符输入流的父类,定义了所有字符输入流都具有的共同特征。其内部提供的方法如下:

image

上图中重载的三个read()方法都是用来读数据的。

  • int read():每次读取一个字符,并把它转换为 0~65535 的整数,然后返回读取到的字符。读到末尾返回-1。(为了提高 I/O 操作的效率,建议尽量使用下面两种read()方法)
  • int read(char[] cbuf):将读取到的多个字符存储到 cbuf 中,然后返回读取的字符,读到末尾时返回-1。
  • int read(char[] cbuf,int off,int len):将读取到的多个字符存储进字符数组 cbuf,从索引 off 开始,长度为len字符,返回结果为读取的字符数.


其中Reader的子类FileReader是专门用于读取文件中的数据,通过它将目标设备上的数据读入到程序。

  FileReader读入文件举例(读取的hello.txt文件内容是:你好,我是中国人!):

package com.thr;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;

/**
 * @author Administrator
 * @date 2020-02-23
 * @desc 字符输入流FileReader
 */
public class FileReaderTest {

    public static void main(String[] args)  {
        //定义输入流
        FileReader fr =null;
        try {
            //1、创建文件对象
            File file = new File("D:\\IO\\hello.txt");
            //2、创建输入流对象
            fr = new FileReader(file);

            //循环读取,读取到末尾返回-1
            int len ;//记录每次读取的字节个数
            while((len = fr.read())!=-1){
                System.out.print((char)len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //释放资源
            try {
                fr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
运行结果:
你好,我是中国人!


2、字符输出流Writer

    Writer是所有字符输出流的父类,定义了所有字符输出流都具有的共同特征。其内部提供的方法如下:

image

上图中重载的五个write()方法都是用来写数据的。

  • void write(int c):把一个字符写入到文件中。
  • void write(char[] cbuf):把cbuf字符数组写入到文件中。
  • void write(char[] cbuf,int off,int len):把部分字符数组写入到文件中,从 cbuf 数组的 off 索引开始,写入len个字符。
  • void write(String str):把一个字符串写入到文件中。
  • void write(String str,int off,int len):把部分字符串写入到文件中,从 字符串的 off 索引开始,写入len个字符。


其中Writer的子类FileWriter是门用于读出文件中的数据,通过它将数据从程序输出到目标设备。

    FileWriter输出文件举例:

package com.thr;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

/**
 * @author Administrator
 * @date 2020-02-23
 * @desc 字符输出流FileWriter
 */
public class FileWriterTest {

    public static void main(String[] args)  {
        //定义输出流
        FileWriter fw =null;
        try {
            //1、创建文件对象
            File file = new File("D:\\IO\\a.txt");
            //2、创建输出流对象,保留原来的数据,在文件后面追加
            fw = new FileWriter(file,true);

            //write():写出一个字符(utf-8编码)
            fw.write(20200223);
            fw.write("\r\n");//回车换行

            //write(char[] buffer):把cbuf字符数组写入到文件中。
            fw.write("我是中国人".toCharArray());
            fw.write("\r\n");

            //write(char[] cbuf,int off,int len):把部分字符数组写入到文件中,从 cbuf 数组的 off 索引开始,写入len个字符。
            fw.write("我是中国人".toCharArray(),1,4);
            fw.write("\r\n");

            //write(String str):把一个字符串写入到文件中。
            fw.write("中国人");
            fw.write("\r\n");

            //write(String str,int off,int len):把部分字符串写入到文件中,从 字符串的 off 索引开始,写入len个字符。
            fw.write("你好,我是中国人\n",3,6);

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //释放资源
            try {
                fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

    注意:如果字符输出流不调用close()方法关闭资源,数据只是保存到缓冲区,并不会保存到文件(这一点与FileOutputStream不同,即使它不调用close()方法依然会写入到文件中)。

    这里就得介绍一下flush()这个方法。

    flush()和close()方法的区别:

    flush():将流中的缓冲区缓冲的数据刷新到目的地中,刷新后,流还可以继续使用。

    close():关闭资源,但在关闭前会将缓冲区中的数据先刷新到目的地,否则丢失数据,然后在关闭流。流不可以使用。

    而当我们亲自去使用flush()方法的时候会产生一个疑问,就算我们在close()之前不加flush()方法也不会影响文件的写出呀,那为什么还要用这个方法呢?先看一下下面的代码吧:

package com.thr;

import java.io.FileWriter;
import java.io.IOException;

/**
 * @author Administrator
 * @date 2020-02-24
 * @desc flush方法的使用
 */
public class WriterFlushTest {

        public static void main(String[] args) {

            //定义输出流
            FileWriter fw = null;

            //其实该步就是在明确数据要存放的目的地
            try {
                fw=new FileWriter("D:\\flush.txt");
                fw.write("");//调用write方法,将字符串写入到流中(使用write其实并没有将字符串直接写入到指定文件,而是存放在流中)
                fw.flush();//这一步才是将上一步write的所写的字符串冲刷到指定的文件(在指定的文件打开后有字符串存在了)

                fw.write("");
                fw.flush();

                fw.write("flush方法");
                fw.flush();

                fw.close();//close()是一定要做的(其实close方法中调用了flush方法)

                fw.write("CCC");//close后若再write,会提示IO异常Stream closed

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
}

       小声BB:我认为flush()方法可有可无,它就是将缓冲区的数据强制写入到文件中,因为在调用完write()方法后数据并没有写入到文件中,而是保存在流中,此时我们可以调用flush()方法,也可以在最后用close()方法来将数据写入文件,因为在close()的时候,也会进行一次flush的,因此close之前其实可以不用专门做flush的。但是在某些情况下,数据量较大的时候,在写的过程中,可以进行阶段性的flush。(话说我也不知道这样做会有什么好处……006DDA0B006DDA0B006DDA0B


3、字符流拷贝文件

package com.thr;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

/**
 * @author Administrator
 * @date 2020-02-23
 * @desc 拷贝文本文件
 */
public class FileReaderWriterTest {

    public static void main(String[] args)  {
        //定义输入流
        FileReader fr =null;
        //定义输出流
        FileWriter fw =null;
        try {
            //创建读入文件对象
            File f1 = new File("D:\\IO\\hello.txt");
            //创建读出文件对象
            File f2 = new File("C:\\a.txt");

            fr = new FileReader(f1);
            fw = new FileWriter(f2);

            //循环读取,读取到末尾返回-1
            char chars[] = new char[1024];
            int len ;//记录每次读取的字节个数
            while((len = fr.read(chars))!=-1){
                fw.write(chars,0,len);
            }
            System.out.println("拷贝成功...");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //释放资源
            try {
                fr.close();
                fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

猜你喜欢

转载自www.cnblogs.com/tanghaorong/p/12345255.html