IO流总结

1. IO流概念

    InputOutputStream - 输入输出流
    Java程序输入输出数据的方式

2. IO流的分类

    根据方向可以分为 输入流 输出流
    根据操作的内容的不同 分为 字节流 和 字符流

    两两相乘就得到了四大基本流:
            输入流 输出流
        字符流 Reader  Writer
        字节流 InputStream OutputStream
    这四大基本流都是抽象的,使用时通常使用这些抽象类的具体实现类

字符输入流 Reader - FileReader

    构造方法:
        构造方法摘要
        FileReader(File file) 
                  在给定从中读取数据的 File 的情况下创建一个新 FileReader。
        FileReader(String fileName) 
                  在给定从中读取数据的文件名的情况下创建一个新 FileReader。
    重要方法:
         int    read() 
                      读取单个字符。
         int    read(char[] cbuf) 
                      将字符读入数组。
        abstract  int   read(char[] cbuf, int off, int len) 
                      将字符读入数组的某一部分。
        abstract  void  close() 
                      关闭该流并释放与之关联的所有资源。
    **为什么read方法返回的不是char而是Int
    因为read如果返回的是char,则无法用任意的char表示到达了文件的结尾,所以此处不返回char 而是返回int,正常情况下返回的是正数,强转为char即可得到对应字符,而当读取到文件结尾返回-1表示 

    案例:编写一个流 来读取外部文件中的字符数据 
    package cn.tedu.io;

            import java.io.FileReader;
            import java.io.Reader;

        /**
             * 案例:编写一个流 来读取外部文件中的字符数据   
             */
            public class Demo01 {
                public static void main(String[] args) throws Exception {
                    //1.创建文件字符输入流链接到 1.txt上
                    Reader reader = new FileReader("1.txt");
                    //2.通过流读取文件中的数据
                    int i = 0;
                    while((i=reader.read())!=-1){
                        System.out.println((char)i);
                    }
                    //3.关闭流
                    reader.close();
                }
            }

字符流-字符输出流-Wirter-FileWriter

    构造方法
        构造方法摘要
        FileWriter(File file) 
                  根据给定的 File 对象构造一个 FileWriter 对象。
        FileWriter(String fileName) 
                  根据给定的文件名构造一个 FileWriter 对象。

    重要方法
        void    write(char[] cbuf) 
                      写入字符数组。
        abstract  void  write(char[] cbuf, int off, int len) 
                      写入字符数组的某一部分。
         void   write(int c) 
                      写入单个字符。
        abstract  void  close() 
                      关闭此流,但要先刷新它。
        abstract  void  flush() 
                      刷新该流的缓冲。
    **在输出数据时,有部分数据可能会被缓冲在流的内部,通过调用flush()可以强制刷新流,将缓存在流内部的数据刷出出去,所以在writer()之后 最好做一次flush()
    **调用close()方法时,close()方法内部会隐含的做一次flush()防止在关流时有数据死在缓冲区内

    案例:编写一个流 来讲指定的字符写出到外部文件中
package cn.tedu.io;

            import java.io.FileWriter;
            import java.io.Writer;

            /**
             * 案例:编写一个流 来将指定的字符写出到外部文件中
             */
            public class Demo02 {
                public static void main(String[] args) throws Exception {
                    //1.创建文件字符输出流
                    Writer writer = new FileWriter("2.txt");
                    //2.通过字符输出流输出数据
                    writer.write((int)'a');
                    writer.write((int)'b');
                    writer.write((int)'c');
                    writer.write((int)'d');
                    writer.write((int)'e');
                    //3.刷新流
                    //writer.flush();
                    //--关闭流,关闭流过程中会隐含的刷新一次流
                    writer.close();
                }
            }

关闭流的过程

IO流用过之后必须关闭,但是IO流的代码中往往存在大量的异常,为了保证关流的操作一定会被执行,所以通过关流都在finally代码块中进行。
而为了保证finally中可以看到流对象,通常都要外置定义流对象。
又由于close方法本身有异常,需要再次捕获异常。
而在finally里通过将引用置为null 使其成为垃圾 可以被回收。
        finally {
                //3.关闭流
                if(reader!=null){
                    try {
                        reader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally{
                        reader = null;
                    }
                }
                if(writer!=null){
                    try {
                        writer.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally{
                        writer = null;
                    }
                }
            }

案例:编写流来拷贝文件
    package cn.tedu.io;

    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.Reader;
    import java.io.Writer;

    /**
     * 案例:利用字符流实现字符文件的拷贝 1.txt -> 3.txt
     */
    public class Demo03 {
        public static void main(String[] args) {
            Reader reader = null;
            Writer writer = null;
            try {
                //1.创建字符输入流 连接1.txt 创建字符输出流 连接3.txt
                reader= new FileReader("1.txt");
                writer = new FileWriter("3.txt");
                //2.从1.txt读取数据
                int i = 0;
                while((i = reader.read())!=-1){
                    writer.write(i);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //3.关闭流
                if(reader!=null){
                    try {
                        reader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally{
                        reader = null;
                    }
                }
                if(writer!=null){
                    try {
                        writer.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally{
                        writer = null;
                    }
                }
            }

        }
    }

    **由于一次拷贝一个字节 效率非常低  我们可以自定义一个缓冲区

    package cn.tedu.io;

    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.Reader;
    import java.io.Writer;

    /**
     * 通过字符流 拷贝字符文件 讨论效率问题
     */
    public class Demo04 {
        public static void main(String[] args){
            //--开始时间
            long begin = System.currentTimeMillis();

            Reader reader = null;
            Writer writer = null;
            try {
                //1.创建流
                reader = new FileReader("4.txt");
                writer = new FileWriter("5.txt");
                //2.拷贝数据
                //int count = 0;
                int i = 0;
                char [] buf = new char [1024];
                while ((i = reader.read(buf)) != -1) {
                    //System.out.println("读取了"+(++count)+"次");
                    writer.write(buf,0,i);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //3.关闭流
                if(reader!=null){
                    try {
                        reader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally{
                        reader = null;
                    }
                }
                if(writer!=null){
                    try {
                        writer.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        writer = null;
                    }
                }
            }
            //--结束时间
            long end = System.currentTimeMillis();
            System.out.println("====共耗时:"+(end-begin)+"ms====");

        }
    }

缓冲流概述

java提供了自带缓冲区的流 BufferedReader bufferedWriter,内部自带缓冲区

功能:
    装饰其他流 提升读写性能
    装饰起来流 提供额外方法

 重要API
    构造方法:
        构造方法摘要
        BufferedReader(Reader in) 
                  创建一个使用默认大小输入缓冲区的缓冲字符输入流。
        BufferedReader(Reader in, int sz) 
                  创建一个使用指定大小输入缓冲区的缓冲字符输入流。
    重要方法:

        String  readLine() 
                      读取一个文本行。

    构造方法:
        构造方法摘要
        BufferedWriter(Writer out) 
                  创建一个使用默认大小输出缓冲区的缓冲字符输出流。
        BufferedWriter(Writer out, int sz) 
                  创建一个使用给定大小输出缓冲区的新缓冲字符输出流。
    重要方法:
         void   newLine() 
                      写入一个行分隔符。

案例:利用缓冲流 包装普通的文件流 复制文件

        package cn.tedu.io;
            import java.io.BufferedReader;
            import java.io.BufferedWriter;
            import java.io.FileReader;
            import java.io.FileWriter;
            import java.io.IOException;

            /**
             * BufferedReader和BufferedWriter提供的新方法
             * 
             * BufferedReader
             *  readline()
             * 
             * BufferedWriter
             *  newLine() 
             */
            public class Demo06 {
                public static void main(String[] args) throws Exception {
                    //1.创建流 并用缓冲流包装
                    BufferedReader reader = new BufferedReader(new FileReader("1.txt"));
                    BufferedWriter writer = new BufferedWriter(new FileWriter("2.txt"));

                    //2.对接流 拷贝文件
                    String line = null;
                    while((line = reader.readLine())!=null){
                        writer.write(line);
                        writer.newLine();
                    }

                    //3.关闭流
                    reader.close();
                    writer.close();

                }
            }

字节流-字节输入流-InputStream-FileInputStream

构造方法:
    构造方法摘要
    FileInputStream(File file) 
              通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。
    FileInputStream(String name) 
              通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。
重要方法:
    int read() 
                  从此输入流中读取一个数据字节。
     int    read(byte[] b) 
                  从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。
     int    read(byte[] b, int off, int len) 
                  从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。
     void   close() 
                  关闭此文件输入流并释放与此流有关的所有系统资源。

**其中read()方法读取字节信息,但返回的是一个int,这是因为如果返回byte,则无论返回什么都无法表示读取到文件结尾的状态,所以read()方法 返回的是int,正常读取到数据时都是正数,直接强转就可以得到对应byte,而当读取到文件结尾时,返回一个-1,作为特殊状态值。
    案例:利用字节流复制文件
        package cn.tedu.io2;

        import java.io.FileInputStream;
        import java.io.FileOutputStream;
        import java.io.InputStream;
        import java.io.OutputStream;

        /**
         * 利用字节流实现文件的复制
         */
        public class Demo01 {
            public static void main(String[] args) throws Exception {
                //1.创建流
                InputStream in = new FileInputStream("1.wmv");
                OutputStream out = new FileOutputStream("2.wmv");
                //2.对接流 实现复制
                int i = 0;
                while((i = in.read())!=-1){
                    out.write(i);
                }
                //3.关闭流
                in.close();
                out.close();
            }
        }

    案例:利用字节流复制文件 - 使用自定义的缓冲区
        package cn.tedu.io2;

        import java.io.FileInputStream;
        import java.io.FileOutputStream;
        import java.io.InputStream;
        import java.io.OutputStream;

        /**
         * 利用字节流实现文件的复制 - 使用缓冲区
         */
        public class Demo02 {
            public static void main(String[] args) throws Exception {
                //1.创建流
                InputStream in = new FileInputStream("1.wmv");
                OutputStream out = new FileOutputStream("2.wmv");
                //2.对接流 实现复制
                int i = 0;
                byte [] tmp = new byte[1024];
                while((i = in.read(tmp))!=-1){
                    out.write(tmp,0,i);
                }
                //3.关闭流
                in.close();
                out.close();
            }
        }

字节流-字节输出流-OutputStream-FileOutputStream

构造方法:
**通过boolean的append参数,可以指定数据是否追加,如果传入false(默认就是false)则,会产生新的文件覆盖旧的文件,如果传入true,则在原有文件的基础上进行追加
    构造方法摘要
    FileOutputStream(File file) 
              创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
    FileOutputStream(File file, boolean append) 
              创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
    FileOutputStream(String name) 
              创建一个向具有指定名称的文件中写入数据的输出文件流。
    FileOutputStream(String name, boolean append) 
              创建一个向具有指定 name 的文件中写入数据的输出文件流。
普通方法:
     void   write(byte[] b) 
                  将 b.length 个字节从指定 byte 数组写入此文件输出流中。
     void   write(byte[] b, int off, int len) 
                  将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。
     void   write(int b) 
                  将指定字节写入此文件输出流。
    void    flush() 
                  刷新此输出流并强制写出所有缓冲的输出字节。
    void    close() 
                  关闭此文件输出流并释放与此流有关的所有系统资源。

    **在利用输出流输出数据的过程中,流的底层具有缓冲机制提升效率,但同时也有可能造成部分数据堆积在底层流的缓冲区中,一时无法写出,此时可以调用flush()方法,手动的将流中缓冲的数据写出
    **close()方法关闭流,在关闭流的过程中,会隐含的调用一次flush() 保证不会有数据死在缓冲区里。

1. 转换流概述

字符流的底层也是字节流,只不过在字节流的基础上增加了缓冲区和编解码器。
字符流内置的编解码器默认采用的编码集是系统码,并且无法修改。
这在使用字符流读写非系统码的字符数据时就会造成乱码。
此时无法通过字符流解决,java提供了转换流,可以自己编写字节流读取数据,再通过转换流转换为字符流,并且在这个过程中自己手动指定码表,从而实现采用指定码表的自定义字符流。

转换流API
java.io
类 InputStreamReader
构造方法:
构造方法摘要
InputStreamReader(InputStream in)
创建一个使用默认字符集的 InputStreamReader。
InputStreamReader(InputStream in, String charsetName)
创建使用指定字符集的 InputStreamReader。

    java.io 
    类 OutputStreamWriter
    构造方法:
        构造方法摘要
        OutputStreamWriter(OutputStream out) 
                  创建使用默认字符编码的 OutputStreamWriter。
        OutputStreamWriter(OutputStream out, String charsetName) 
                  创建使用指定字符集的 OutputStreamWriter。
        案例:拷贝一个utf-8编码集 包含中文的文本文件 要求产生的文件也是utf-8编码
            package cn.tedu.io2;

            import java.io.FileInputStream;
            import java.io.FileOutputStream;
            import java.io.InputStream;
            import java.io.InputStreamReader;
            import java.io.OutputStream;
            import java.io.OutputStreamWriter;

            /**
             * 案例:通过转换流 生成自定义码表的字符流 复制文件 解决乱码
             */
            public class Demo04 {
                public static void main(String[] args) throws Exception {
                    //1.创建字节流
                    InputStream in = new FileInputStream("d://8.txt");
                    OutputStream out = new FileOutputStream("d://9.txt");

                    //2.创建转换流 将字节流转换为字符流 并显式指定码表为utf-8
                    InputStreamReader reader = new InputStreamReader(in,"utf-8");
                    OutputStreamWriter writer = new OutputStreamWriter(out,"utf-8");

                    //3.对接流 复制文件
                    char [] data = new char[1024];
                    int i = 0;
                    while((i=reader.read(data))!=-1){
                        writer.write(data,0,i);
                    }

                    //4.关闭流
                    reader.close();
                    writer.close();
                }
            }


        案例:拷贝一个utf-8编码集 包含中文的文本文件 要求产生的文件是gbk编码
            package cn.tedu.io2;

            import java.io.FileInputStream;
            import java.io.FileOutputStream;
            import java.io.InputStream;
            import java.io.InputStreamReader;
            import java.io.OutputStream;
            import java.io.OutputStreamWriter;

            /**
             * 案例:通过转换流 生成自定义码表的字符流 复制文件 将utf-8文件转换为gbk格式的文件
             */
            public class Demo05 {
                public static void main(String[] args) throws Exception {
                    //1.创建字节流
                    InputStream in = new FileInputStream("d://8.txt");
                    OutputStream out = new FileOutputStream("d://9.txt");

                    //2.创建转换流 将字节流转换为字符流 并显式指定码表为utf-8
                    InputStreamReader reader = new InputStreamReader(in,"utf-8");
                    OutputStreamWriter writer = new OutputStreamWriter(out,"gbk");

                    //3.对接流 复制文件
                    char [] data = new char[1024];
                    int i = 0;
                    while((i=reader.read(data))!=-1){
                        writer.write(data,0,i);
                    }

                    //4.关闭流
                    reader.close();
                    writer.close();
                }
            }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值