IO 流之字符流的緩衝區

  1. 緩衝區的出現提升了對數據的讀寫效率
  2. 對應類:
    1. BufferedWriter
    2. BufferedReader
  3. 緩衝區須要結合流才能夠使用, 對流的功能進行了加強, 即對流的操做起到裝飾做用

使用緩衝區實現文本文件的寫入和讀取

// 寫入
public class BufferedWriterDemo{
    public static void main(String[] args) throws IOException {

        FileWriter fw = new FileWriter("buf.txt");

        // 爲了提升寫入的效率, 使用了字符流的緩衝區
        // 建立了一個字符寫入流的緩衝對象, 並和指定要被緩衝的流對象相關聯

        BufferedWriter bufw = new BufferedWriter(fw);

        // 使用緩衝區的寫入方法將數據寫入到緩衝區中
        bufw.write("abcde");

        // 換行, 其實就是封裝了系統屬性  line.separator
        // BufferedWriter 特有方法
        bufw.newLine();

        bufw.newline("hahaha");

        // 使用緩衝區的刷新方法將數據刷入到目的地中
        bufw.flush();

        // 關閉緩衝區, 其實關閉的就是被緩衝的流對象
        bufw.close();
    }
}

// 讀取
public class BufferedReaderDemo {
    public static void main(String[] args){

        FileReader fr = new FileReader("buf.txt");
        BufferedReader bufr = new BufferedReader();

        /*  讀取字符數組的方式
         *
         *  char[] buf = new char[1024];

         *  int len = 0;
         *  while((len=bufr.read(buf))!= -1){
         *  System.out.println(new String(buf,0,len));
         *  }
         */

         // 按一行讀取, BufferredReader 特有方法: readLine()
         // 若是到達流末尾, 返回 null
         String line = null;
         while((line=bufr.readLine()) != null){  // 注意: 此處判斷的是 != null
            System.out.println(line);
        }

        // 關閉緩衝區
        bufr.close();
    }
}

BufferedReader 中的 readLine() 方法原理

  • BufferedReader 類複寫了父類的如下方法:
    • read(); : 讀取單個字符
    • read(char[] buf, int off, int len); : 讀取數組的一部分
  • BufferedReader 類本身特有的方法 readLine()
  • BufferedReader 類繼承了父類方法:
    • read(char[] buf) : 將字符讀入數組

readLine() 方法原理: 使用了讀取緩衝區的 read() 方法, 將讀取到的字符進行緩衝並判斷換行標記. 將標記前的緩存數據變成字符返回.html

模擬實現 BufferedReader

// 需求: 自定義的讀取緩衝區, 其實就是模擬一個 BufferedReader

/* 分析:
 *    緩衝區中無非就是封裝了一個數組, 並對外提供了更多的方法對數組進行訪問
 *    其實這些方法最終操做的都是數組的角標
 *
 *     緩衝區原理: 其實就是從源中獲取一批數據裝進緩衝區中, 在從緩衝區中不斷
 *     的取出一個一個數據.
 *     
 *     在緩衝區中數據這次取完後, 在從源中繼續取一批數據進緩衝區, 當源中的數據取光時,
 *     用 -1 做爲結束標記
 */

 public class MyBufferedReader{

    private FileReader r;

    // 定義一個數組做爲緩衝區
    private char[] buf = new char[1024];

    // 定義一個指針用於操做這個數組中的元素, 當操做到最後一個元素時, 指針應該歸 0
    private int pos = 0;

    // 定義一個計數器, 記錄緩衝區中的數據個數. 當該數據減到0, 就從源中繼續獲取數據到緩衝區中
    private int count = 0;

    // 帶參數的構造函數, 指定加強的流對象
    public MyBufferedReader(FileReader r){
        this.r = r;
    }

    // 定義從緩衝區讀取單個字符的 read() 方法
    public int myRead() throws IOException{

        // 1. 從源中獲取一批數據到緩衝區中, 須要先作判斷, 只有計數器爲 0 時, 才須要從源中獲取數據
        /* if(count == 0){

         *   // 記錄從源中獲取的數據個數
         *   count = r.read(buf);

         *   if(count < 0){
         *      return -1;
         *  }

         *  // 每次從源中獲取數據到緩衝區後, 角標歸零
         *   pos = 0;

         *   // 獲取第一個數據
         *   char ch = buf[pos];

         *   pos++;
         *   count--;

         *   return ch;
         *   } else {

         *   char ch = buf[pos];

         *   pos++;
         *   count--;

         *   return ch;
         *   }
         */
        // 代碼優化:

        if(count == 0){
            count = r.read(buf);

            pos = 0;
        }

        if(count < 0){
            return -1;
        }

        char ch = buf[pos++];

        count--;

        return ch;
    }

    // 定義從緩衝區讀取一行字符的 readLine() 方法
    public String myReadLine() throws IOException{

        // 定義一個數組容器, 存儲從緩衝區中獲取到的數據
        StringBuilder sb = new StringBuilder();

        // 使用自定義的 MyRead 方法, 從緩衝區中不斷獲取單個字符,
        int ch = 0;
        while((ch=myRead()) != -1){

            if(ch=='\r')
                continue;
            if(ch=='\n')
                return sb.toString();

            // 將從緩衝區中讀到的字符, 存儲到緩存行數據的緩衝區中
            sb.append((char)ch);
        }

        // 若是最後一行結尾沒有回車符, 緩衝區的讀取已結束,
        // 可是並不能判斷 if(ch=='\n'), 全部最後一行未能輸出
        if(sb.length() != 0)
            return sb.toString();

        return null;
    }

    public void myClose() throws IOException{
        r.close();
    }

    }

使用緩衝區的方式複製文本文件

public class CopyTextByBufTest {
    public static void main(String[] args) throws IOException {
        FileReader fr = new FileReader("buf.txt");
        BufferedReader bufr = new BufferedReader(fr);

        FileWriter fw = new FileWriter("buf_copy.txt");
        BufferedWriter bufw = new BufferedWriter(fw);

        /*
         *  int ch = 0;
         *  // 使用緩衝區對象進行單個字符的讀寫
         *  // 這是直接從內存中讀取單個字符, 不是從硬盤中
         *  while((ch=bufr.read()) != -1){
         *        bufw.write(ch);
         *    }
         */

         // 使用行進行讀取文件

         String line = null;
         while((line=bufr.readLine())!=null){
            bufw.write(line);
            bufw.newLine();
            bufw.flush();  // 注意: 每次寫入以後, 進行刷新保存
        }

        bufw.close();
        bufr.close();
}
}

LineNumberReader 裝飾類

  1. BufferedReader 的子類
  2. 能夠跟蹤行號的緩衝字符輸入流
    • setLineNumber(int); : 設置當前行號
    • getLineNumber(); : 獲取當前行號



參考資料api

相關文章
相關標籤/搜索