zoukankan      html  css  js  c++  java
  • 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("
    ");//回车换行
    
                //write(char[] buffer):把cbuf字符数组写入到文件中。
                fw.write("我是中国人".toCharArray());
                fw.write("
    ");
    
                //write(char[] cbuf,int off,int len):把部分字符数组写入到文件中,从 cbuf 数组的 off 索引开始,写入len个字符。
                fw.write("我是中国人".toCharArray(),1,4);
                fw.write("
    ");
    
                //write(String str):把一个字符串写入到文件中。
                fw.write("中国人");
                fw.write("
    ");
    
                //write(String str,int off,int len):把部分字符串写入到文件中,从 字符串的 off 索引开始,写入len个字符。
                fw.write("你好,我是中国人
    ",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();
                }
            }
        }
    }
  • 相关阅读:
    Spring@Profile注解
    day 32 子进程的开启 及其用法
    day 31 udp 协议SOCK_DGRAM
    day 30 客户端获取cmd 命令的步骤
    day 29 socket 理论
    day 29 socket 初级版
    有关 组合 继承
    day 27 多态 接口 类方法 静态方法 hashlib 摘要算法模块
    新式类和经典类的区别
    day 28 hasattr getattr serattr delattr 和带__内置__ 类的内置方法
  • 原文地址:https://www.cnblogs.com/tanghaorong/p/12345255.html
Copyright © 2011-2022 走看看