(六)字符流的缓冲区

作者: 黒猫 | 来源:发表于2017-03-12 17:32 被阅读84次

    1、字符缓冲流基本介绍

    缓冲区的出现提高了IO流对数据的读写效率,但缓冲区仅具备提高效率的功能,不具备读或写的功能,因此必须要结合IO流才可以使用,实际上是在IO流本身的基础上对IO流的功能进行了增强。

    缓冲区对应字符流的类:

    BufferedWriter:只能提高效率,不能进行写入操作
    BufferedReader:只能提高效率,不能进行读取操作


    2、使用缓冲输出流实现对文件的写入

    import java.io.BufferedWriter;
    import java.io.FileWriter;
    import java.io.IOException;
    
    public class Demo1 {
    public static void main(String[] args) throws IOException {
    
    /*
     * 1.因为BufferedWriter只能提高效率,不能进行写入操作
     * 因此创建文件写入流对象,并且要和被写入数据的文件进行关联
     */
    
            FileWriter fr = new FileWriter("F:\\Demo1.txt");
    
    /*
     * 2.为了提高写入效率,使用缓冲写入流
     * 把需要提高效率的字符输出流对象作为参数传递给BufferedWriter的构造方法
     */
                
            BufferedWriter bw = new BufferedWriter(fr);
            
    //3.使用BufferedWriter对象实现写入数据
    
            for(int i = 1;i<=3;i++){
                bw.write(i+":"+"简书");
                bw.newLine();//可跨平台显示的换行
                //bw.flush();
                
                /*
                 * 为了更进一步提高效率
                 * 不建议在此时使用flush()方法刷新
                 * 可在最后关闭程序时统一刷新写入 
                 */
            
            }
    
    //4.关闭流
    
            bw.close();//关闭缓冲流相当于关闭了原本的字符流
    }
    }
    

    3、使用缓冲输入流实现对文件的读取

    import java.io.BufferedReader;
    import java.io.FileReader;
    import java.io.IOException;
    
    public class Demo2 {
    public static void main(String[] args) throws IOException {
    
    /*
     * 1.因为BufferedReader只能提高效率,不能进行读取操作
     * 因此创建文件读取流对象,并且要和被读取数据的文件进行关联
     */
    
            FileReader fr = new FileReader("F:\\Demo1.txt");
    
    /*
     * 2.为了提高读取效率,使用缓冲读取流
     * 把需要提高效率的字符输入流对象作为参数传递给BufferedReader的构造方法
     */
            BufferedReader br = new BufferedReader(fr);
            
    /*
     * 3.使用BufferedReader对象实现读取数据
     * BufferedReader类中有一个每次读取一个文本行的方法readLine()
     */
    
            String line = null;
            while((line=br.readLine())!=null){//返回包含该行内容的字符串,不包括最后的换行符
                System.out.println(line);
            }
    
    //4.关闭流
    
            br.close();
            
    }
    }
    
    

    4、使用缓冲流实现复制文件

    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    
    public class Demo3 {
    public static void main(String[] args) {
    
    /*
     * 创建局部变量保证br、br的作用域为整个方法
     * 同时为了防止其他异常
     * 给引用变量bw、br赋一个初始值null
     */
    
            BufferedReader br = null;
            BufferedWriter bw = null;
    
    //使用try块包裹代码,用catch块捕获IO异常
            
            try {
                br = new BufferedReader(new FileReader("E:\\Demo1.java"));
                bw = new BufferedWriter(new FileWriter("F:\\Demo1_Copy.java"));
    
    //将字符读入数组
                
                String line = null;
                while((line = br.readLine())!=null){
                    bw.write(line);
                    bw.newLine();//写入换行         
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            finally{
    
            /*
             * close()方法是一定要执行的
             * 因此放入finally块中
             * 同时该方法要求处理异常
             * 因此需要再用try_catch操作
             */
    
                try{
    
            /*
             * 如果路径错误,例如 new FileWriter("Z:\\Demo1.java");
             * 将导致FileWriter对象创建失败,从而导致BufferedWriter对象创建失败
             * 致使finally块的close()方法中的bw不存在,变为null.close();
             * 从而引发NullPointException异常,因此要加入if(bw!= null)的判断
             */
    
                    if(bw!= null){
                        bw.close();
                    }
                }catch(IOException e){
                    e.printStackTrace();
                }
    
                try{
                    if(br!= null){
                        br.close();
                    }
                }catch(IOException e){
                    e.printStackTrace();
                }
            }
    }
    }
    
    

    5、缓冲流实现原理

    此部分为扩展内容,仅供了解

    import java.io.FileReader;
    import java.io.IOException;
    import java.io.Reader;
    
    /**
     * 模拟BufferedReader,自定义一个类MyBufferedReader,思路如下:
     * 1.需要一个真正具备读功能的流对象,所以MyBufferedReader需要定义一个Reader类型的成员
     * 2.需要提供一个缓冲区来提高效率,所以需要定义一个数组充当缓冲区
     * 3.操作数组需要下标,所以需要定义一个下标
     * 4.统计字符的个数,所以需要定义一个变量
     * 5.自定3个功能:读取单个字符,每次读取一行,关闭流
     * @param args
     */
    
    class MyBufferedReader{
        private Reader r;//具备读功能的成员
        private char[] arr = new char[1024];//提高效率的缓冲区
        private int index;//下标
        private int count;//统计缓冲区中字符个数
        
    public MyBufferedReader(Reader r){
            this.r = r;
        }
    
    //1.一次读取一个的功能
    
    public int myRead()throws IOException{      
            if(count==0){//先判断缓冲区中是否有字符 
                count = r.read(arr);//从文件中读一批数据到缓冲区
                index = 0;//下标置为0,从头开始取
            }
            if(count<0){
                return -1;
            }
            int num = arr[index];//从缓冲区取一个字符
            count--;//字符数量减一
            index++;//下标加一
            return num;
    }
    
    /*
     * 2.一次读取一行的功能
     * 反复调用myRead()方法,不满一行的时候存储数据,满一行的时候返回
     */
    
    public String myReadLine() throws IOException{
        StringBuilder sb = new StringBuilder();//实现存储字符
        int num;
        while((num = myRead())!=-1){
            if(num=='\r'){//Windows下换行的转义字符为"\r\n"          
            continue;//如果是'\r',说明不满一行,继续
            }else if(num == '\n'){/如果是'\n',说明满一行
                return sb.toString();//输出该行
            }else{
                sb.append((char)num);//不满一行时存储数据
            }
        }return null;
    }
    
    //3.关闭
    
    public void myClose() throws IOException{
        r.close();
    }
    }
    
    
    
    //使用main()方法测试自定义类MyBufferedReader
    
    public class MyBufferedReaderTest {
    public static void main(String[] args) throws IOException {
    
            FileReader fr = new FileReader("F:\\Demo1.txt");
            MyBufferedReader mbr = new MyBufferedReader(fr);
    
            String line = null;
            while((line = mbr.myReadLine())!=null){
                    System.out.println(line);
            }
            mbr.myClose();
    }
    }
    
    

    6、LineNumberReader

    LineNumberReader作为BufferedReader的子类,同样属于装饰类,不仅具有BufferedReader提高效率的功能,还有自己所独有的显示和设置行号的功能。

    import java.io.FileReader;
    import java.io.IOException;
    import java.io.LineNumberReader;
    
    public class lineNumber {
    public static void main(String[] args) throws IOException {
    
            FileReader fr = new FileReader("F:\\Demo1.txt");
            LineNumberReader lnr = new LineNumberReader(fr);
            
            String line = null;
            lnr.setLineNumber(5);//设置5,行号即从6开始
            while((line = lnr.readLine())!=null){
                System.out.println(lnr.getLineNumber()+":"+line);//读取行号
            }
                lnr.close();
            }
    /*
     * 6:简书
     * 7:简书
     * 8:简书
     */
    }
    

    7、LineNumberReader实现原理

    此部分为扩展内容,仅供了解

    import java.io.FileReader;
    import java.io.IOException;
    import java.io.Reader;
    
    /**
     * 模拟LineNumberReader,自定义一个类MyLineNumberReader,思路如下:
     * LineNumberReader在BufferedReader的基础上增加了有关行号的处理方法
     * 由此就想到可以继承之前模拟的MyBufferedReader
     * 再重写myReadLine()方法
     * @param args
     */
    
    class MyLineNumberReader extends MyBufferedReader{//继承MyBufferedReader
        private int lineNumber;
        
    public MyLineNumberReader(Reader r){
            super(r);
        }
    
    public void setLineNumber(int lineNumber){
            this.lineNumber = lineNumber;
        }
    
    public int getLineNumber(){
            return lineNumber;
        }
    
    public String myReadLine() throws IOException{//重写一次读一行功能
            ++lineNumber;
            return super.myReadLine();
    }
    }
    
    
    
    //使用main()方法测试自定义类MyBufferedReader
    
    public class MyLineNumberReaderTest {
    public static void main(String[] args) throws IOException {
            
            FileReader fr = new FileReader("F:\\Demo1.txt");
            MyLineNumberReader mnr = new MyLineNumberReader(fr);
    
            String line = null;
            while((line = mnr.myReadLine())!=null){
                System.out.println(mnr.getLineNumber()+":"+line);
            }
            mnr.myClose();
    }
    }
    

    版权声明:欢迎转载,欢迎扩散,但转载时请标明作者以及原文出处,谢谢合作!             ↓↓↓
    

    相关文章

      网友评论

        本文标题:(六)字符流的缓冲区

        本文链接:https://www.haomeiwen.com/subject/hvjtnttx.html