Java IO流之字符流,帶緩沖的字符流

IO流

看著字少,內容著實不少,這里開始就給諸君推薦一篇大神的博客,總結的思路清晰,鬼斧神工,哈哈,總之總結的很好。見地址:

Java IO流學習總結,也是很好的入坑引言。

Java IO流學習總結
Java IO流學習總結
Java IO流學習總結
寫三次應該有人會傳送過去的吧。

IO分類

  • 按數據類型分為字符流,字節流。
  • 按數據流向分為輸入流,輸出流。

輸入字節流(InputStrem) 輸出字節流(OutputStrem) 字符輸入流(Reader) 字符輸出流(Writer)

我們先看字符輸出流Writer。

字符輸出流----Writer

要了解它,它卻很抽象,孤僻,難以交流,那我們就從它子子孫孫開始。首先我們看它孫子FileWriler。

FileWriter 繼承自OutputStreamWriter

構造方法:

     //創建字符輸出流類對象和已存在的文件相關聯。文件不存在的話,并創建。
     public FileWriter(String var1) throws IOException {
            super(new FileOutputStream(var1));
        }//如:FileWriter fw=new FileWriler("D:files.txt");

      //創建字符輸出流類對象和已存在的文件相關聯,并設置該該流對文件的操作是否為續寫。
     public FileWriter(String var1, boolean var2) throws IOException {
            super(new FileOutputStream(var1, var2));
        }//如:FileWriter fw=new FileWriler("D:files.txt",true);//true表示再次寫入字符的時候為追加,false表示再次寫入字符時,先擦除,在寫入(覆蓋)

      //類似構造方法一
     public FileWriter(File var1) throws IOException {
            super(new FileOutputStream(var1));
        }//如:FileWriter fw=new FileWriter(new File("D:files.txt"));

      //類似構造方法二
     public FileWriter(File var1, boolean var2) throws IOException {
            super(new FileOutputStream(var1, var2));
        }//如:FileWriter fw=new FileWriter(new File("D:files.txt"),flase);//覆蓋寫入

      //不常用
      public FileWriter(FileDescriptor var1) {
            super(new FileOutputStream(var1));
        }//如:

可見構造方法都拋異常的,忘了告訴你,上面的已經是FileWriter所有的代碼了。

主要方法:
  • void write(String str)寫入字符串。當執行完此方法后,字符數據還并沒有寫入到目的文件中去。此時字符數據會保存在緩沖區中。
    此時在使用刷新方法就可以使數據保存到目的文件中去。

  • void flush() 刷新該流中的緩沖。將緩沖區中的字符數據保存到目的文件中。

  • void close() 關閉此流。在關閉前會先刷新此流的緩沖區。在關閉后,再寫入或者刷新的話,會拋IOException異常。

案例
    /**
     * IO流代碼很難看,主要是因為異常處理過多
     */
    public class Demo {
        public static void main(String[] args) {
            FileWriter writer = null;
            FileWriter writer1 = null;

            FileWriter writer2 = null;
            FileWriter writer3 = null;
            try {
                //1. 創建FileWriter對象,并在構造方法中指定文件路徑
                writer = new FileWriter(Config.PATH + "testFileWriter1.txt");//此文件是在當前工程目錄下
                //2.向文件字符中寫入一串文本數據
                writer.write("hello");
                writer.flush();//3、在關閉流之前,先執行刷新//刷一次代表寫入一次

                //構造方法的第二個參數,表示是否追加內容
                writer1 = new FileWriter(Config.PATH + "testFileWriter1.txt");//寫入的新的內容會在原內容的后面增加
                writer1.write("你好-->1");
                writer1.flush();

                //構造方法的第二個參數,表示是否追加內容
                writer2 = new FileWriter(Config.PATH + "testFileWriter2.txt");
                writer2.write("你好-->2");
                writer2.flush();

                //構造方法的第二個參數,表示是否追加內容 true 追加 false 覆蓋
                writer3 = new FileWriter(Config.PATH + "testFileWriter2.txt", false);//寫入的新的內容會覆蓋原內容
                writer3.write("你好-->");
                writer3.flush();
                writer3.write("豬");
                writer3.flush();

            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    writer.close(); //關閉流
                    writer1.close();
                    writer2.close();
                    writer3.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
  • Config中的代碼

      public static final String PATH = "/Volumes/huang/studyfromGitHub/JavaForAndroid/JavaForAndroid/series10/src/main/java/files/";
    
結果

說明默認寫入模式為覆蓋。

字符輸入流----Reader

同樣的看他孫子類。

FileReader 繼承自InputStreamReader

構造方法,也是所有源碼

    //使用帶有指定文件的String參數的構造方法。創建該輸入流對象。并關聯源文件。
    public FileReader(String var1) throws FileNotFoundException {
            super(new FileInputStream(var1));
        }//如:FileReader fr = new FileReader(String file);
    //基本同構造方法一,因為構造方法一傳的String 目的也是創建一個文件
    public FileReader(File var1) throws FileNotFoundException {
            super(new FileInputStream(var1));
        }//如:FileReader fr = new FileReader(new File(str));//str為String類型

    //不常用
    public FileReader(FileDescriptor var1) {
            super(new FileInputStream(var1));
        }//如:
主要方法:
  • void read()讀取單個字符。返回作為整數讀取的字符,如果已達到流末尾,則返回 -1。

  • void read(char[]char) 將字符讀入數組。返回讀取的字符數。如果已經到達尾部,則返回-1。

  • void close() 關閉此流對象。釋放與之關聯的所有資源

案例----我們把上一個案例的testFileWriter2.txt文件內容讀出來
    public class Demo {
        public static void main(String[] args) {
            //1.聲明FileReader對象
            FileReader fileReader = null;
            try {
                //2. 實例化FileReader對象
                fileReader = new FileReader(Config.PATH + "testFileWriter2.txt");//可能會拋出FileNotFoundException異常
                //3.文本讀取
                int num = 0;
                while ((num = fileReader.read()) != -1) {//每次讀一個字符,如果為-1表示已到文件結束位置
                    System.out.print((char) num);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    fileReader.close();//關閉流
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
結果
案例----演示void read(char[]char) 用法
    public class Demo {
        public static void main(String[] args) {
            FileReader fileReader = null;
            try {
                fileReader = new FileReader(Config.PATH + "testFileWriter2.txt");
                char[] buffer = new char[4];//每次最多讀4個字符
                int n = 0;
                while ((n = fileReader.read(buffer)) != -1) {//每次最多讀4個字符,如果為-1表示已到文件結束位置
                    //打印本次讀取的內容,從0位置開始,到本次讀取的字符個數
                    System.out.println("讀取 "+n+"個字符: "+new String(buffer,0,n));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                try {
                    fileReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
結果

可見讀取到的內容都是一樣的。

字符流(FileReader FileWriter)復制文件案例

    /**
     * 需求:copy拷貝 Demo1文件
     * 思路:肯定是邊讀邊寫
     */
    public class Demo {
        //源文件路徑
        public static final String PATH = "/Volumes/huang/studyfromGitHub/JavaForAndroid/JavaForAndroid/series10/src/main/java/com/example/Demo1.java";
        public static final String FILENAME = "copyDemo1.java";

        public static void main(String[] args) {
            // 1. 聲明文件字符的輸入、輸出流對象
            FileReader fileReader = null;
            FileWriter fileWriter = null;

            try {
                // 2. 實例化流操作對象
                fileReader = new FileReader(PATH);
                fileWriter = new FileWriter(Config.PATH + FILENAME);//如果文件不存在,則會自動創建
                char[] buffer = new char[6];
                int len = 0;
                while ((len = fileReader.read(buffer)) != -1) {//邊讀
                    fileWriter.write(buffer, 0, len);//邊寫,將本次讀取的字符寫入到復制的文件中
                }

            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                try {
                    //最后別忘了關閉流
                    fileReader.close();
                    fileWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
結果

標紅不是我的錯,本來就該標紅。

字符輸出流使用緩沖----FileWriter和BufferedWriter

  • FileWriter 文件字符輸出流
  • BufferedWriter 緩沖字符輸出流
BufferedWriter緩沖字符輸出流,直接繼承自Writer

構造方法

public BufferedWriter(Writer var1) {
        this(var1, defaultCharBufferSize);
    }

public BufferedWriter(Writer var1, int var2) {
        super(var1);
        if(var2 <= 0) {
            throw new IllegalArgumentException("Buffer size <= 0");
        } else {
            this.out = var1;
            this.cb = new char[var2];
            this.nChars = var2;
            this.nextChar = 0;
            this.lineSeparator = (String)AccessController.doPrivileged(new GetPropertyAction("line.separator"));
        }
    }

沒看錯的話是兩個,要想得到BufferedWriter實例,必須給它傳一個Writer實例。

運用舉例
public class Demo{
    public static final String NAME = "testDemo5.txt";

    public static void main(String[] args) {
        //1.變量聲明
        FileWriter fileWriter = null;
        BufferedWriter bufferedWriter = null;

        try {
            //2.實例化變量
            fileWriter = new FileWriter(Config.PATH + NAME);
            bufferedWriter = new BufferedWriter(fileWriter);//裝飾者模式,擴展現有功能(包裝),將節點流(文件字符流)對象作為構造參數使用
            //通過緩沖流對象向文本文件中寫入數據
            bufferedWriter.write("哈哈,");
            bufferedWriter.newLine();//換行
            bufferedWriter.write("此處發現一個大傻逼。");
            //此處追加文本數據是向緩沖追加,而非是將內容追加到文件內
            bufferedWriter.append("追加內容")
                    .append("\r\n").append("這里也有一個傻逼。");
            //注:緩沖數據是將數據存入內存中,并沒有寫入到文件中,在關閉流之前必須要執行flush()方法
            bufferedWriter.flush();//將內存的數據寫入到文件中
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                bufferedWriter.close();//處理流關閉之后,節點流會自動關閉
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}
結果

注:緩沖數據是將數據存入內存中,并沒有寫入到文件中,在關閉流之前必須要執行flush()方法。
大家有沒有發現FileWriter被BufferedWriter包裝之后,功能變多了。。。下一篇讓我們來稍微了解一下裝飾者模式。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容