Java攻城狮的入门课程Java学习笔记程序员

(六)字符流的缓冲区

2017-03-12  本文已影响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();
}
}

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

猜你喜欢

热点阅读