17-字節(jié)流养泡、字符流

第一章 IO概述

1.1 什么是IO

我們把數據的傳輸嗜湃,可以看做是一種數據的流動,按照流動的方向澜掩,以內存為基準购披,分為輸入input輸出output ,即流向內存是輸入流肩榕,流出內存的輸出流刚陡。

Java中I/O操作主要是指使用java.io包下的內容,進行輸入株汉、輸出操作筐乳。
輸入也叫做讀取數據
輸出也叫做作寫出數據。

1.2 IO的分類

根據數據的流向分為:輸入流輸出流乔妈。

  • 輸入流 :把數據從其他設備上讀取到內存中的流蝙云。
  • 輸出流 :把數據從內存 中寫出到其他設備上的流。

格局數據的類型分為:字節(jié)流字符流褒翰。

  • 字節(jié)流 :以字節(jié)為單位贮懈,讀寫數據的流。
  • 字符流 :以字符為單位优训,讀寫數據的流朵你。
    1字符=2個字節(jié)
    1字節(jié)=8個二進制位。

1.3 IO的流向說明圖解

1.4 頂級父類們

輸入流 輸出流
字節(jié)流 字節(jié)輸入流<br />InputStream 字節(jié)輸出流<br />OutputStream
字符流 字符輸入流<br />Reader 字符輸出流<br />Writer

第二章 字節(jié)流

2.1 一切皆為字節(jié)

一切文件數據(文本揣非、圖片抡医、視頻等)在存儲時,都是以二進制數字的形式保存早敬,都一個一個的字節(jié)忌傻,那么傳輸時一樣如此。所以搞监,字節(jié)流可以傳輸任意文件數據水孩。在操作流的時候,我們要時刻明確琐驴,無論使用什么樣的流對象俘种,底層傳輸的始終為二進制數據秤标。

2.2 字節(jié)輸出流【OutputStream】

java.io.OutputStream抽象類是表示字節(jié)輸出流的所有類的超類,將指定的字節(jié)信息寫出到目的地宙刘。它定義了字節(jié)輸出流的基本共性功能方法苍姜。

  • public void close() :關閉此輸出流并釋放與此流相關聯(lián)的任何系統(tǒng)資源。
  • public void flush() :刷新此輸出流并強制任何緩沖的輸出字節(jié)被寫出悬包。
  • public void write(byte[] b):將 b.length字節(jié)從指定的字節(jié)數組寫入此輸出流衙猪。
  • public void write(byte[] b, int off, int len) :從指定的字節(jié)數組寫入 len字節(jié),從偏移量 off開始輸出到此輸出流布近。
  • public abstract void write(int b) :將指定的字節(jié)輸出流垫释。

小貼士:

close方法,當完成流的操作時撑瞧,必須調用此方法饶号,釋放系統(tǒng)資源。

2.3 FileOutputStream類

OutputStream有很多子類季蚂,我們從最簡單的一個子類開始茫船。

java.io.FileOutputStream類是文件輸出流,用于將數據寫出到文件扭屁。

構造方法

  • public FileOutputStream(File file):創(chuàng)建文件輸出流以寫入由指定的 File對象表示的文件算谈。
  • public FileOutputStream(String name): 創(chuàng)建文件輸出流以指定的名稱寫入文件。

當你創(chuàng)建一個流對象時料滥,必須傳入一個文件路徑然眼。該路徑下,如果沒有這個文件葵腹,會創(chuàng)建該文件高每。如果有這個文件,會清空這個文件的數據践宴。

  • 構造舉例鲸匿,代碼如下:
public class FileOutputStreamConstructor throws IOException {
    public static void main(String[] args) {
        // 使用File對象創(chuàng)建流對象
        File file = new File("a.txt");
        FileOutputStream fos = new FileOutputStream(file);
      
        // 使用文件名稱創(chuàng)建流對象
        FileOutputStream fos = new FileOutputStream("b.txt");
    }
}

寫入數據的原理(內存→硬盤):java程序→JVM(java虛擬機)→OS(操作系統(tǒng))→OS調用寫數據的方法→把數據寫入到文件中
字節(jié)輸出流的使用步驟
1.創(chuàng)建FileOutputStream對象,構造方法中傳入寫入數據的目的地阻肩。
2.調用FileOutputStream對象中的write方法带欢,把數據寫入到文件中。
3.釋放資源(流的使用會占用一些內存烤惊,使用完畢后把內存清空乔煞,提高程序效率)

寫出字節(jié)數據

  1. 寫出字節(jié)write(int b) 方法,每次可以寫出一個字節(jié)數據柒室,

代碼使用演示:

public class FOSWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名稱創(chuàng)建流對象
        FileOutputStream fos = new FileOutputStream("fos.txt");     
        // 寫出數據
        fos.write(97); // 寫出第1個字節(jié)
        fos.write(98); // 寫出第2個字節(jié)
        fos.write(99); // 寫出第3個字節(jié)
        // 關閉資源
        fos.close();
    }
}
輸出結果:
abc

小貼士:

  1. 雖然參數為int類型四個字節(jié)渡贾,但是只會保留一個字節(jié)的信息寫出。
  2. 流操作完畢后雄右,必須釋放系統(tǒng)資源空骚,調用close方法锦溪,千萬記得。
  1. 寫出字節(jié)數組write(byte[] b)府怯,每次可以寫出數組中的數據,代碼使用演示:
public class FOSWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名稱創(chuàng)建流對象
        FileOutputStream fos = new FileOutputStream("fos.txt");     
        // 字符串轉換為字節(jié)數組
        byte[] b = "黑馬程序員".getBytes();
        // 寫出字節(jié)數組數據
        fos.write(b);
        // 關閉資源
        fos.close();
    }
}
輸出結果:
黑馬程序員
  1. 寫出指定長度字節(jié)數組write(byte[] b, int off, int len) ,每次寫出從off索引開始防楷,len個字節(jié)牺丙,代碼使用演示:
public class FOSWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名稱創(chuàng)建流對象
        FileOutputStream fos = new FileOutputStream("fos.txt");     
        // 字符串轉換為字節(jié)數組
        byte[] b = "abcde".getBytes();
        // 寫出從索引2開始,2個字節(jié)复局。索引2是c冲簿,兩個字節(jié),也就是cd亿昏。
        fos.write(b,2,2);
        // 關閉資源
        fos.close();
    }
}
輸出結果:
cd

數據追加續(xù)寫

經過以上的演示峦剔,每次程序運行官研,創(chuàng)建輸出流對象姚建,都會清空目標文件中的數據,然后覆蓋重寫纠屋。如何保留目標文件中原有數據递礼,還能繼續(xù)添加新數據呢惨险?

  • public FileOutputStream(File file, boolean append): 創(chuàng)建文件輸出流以寫入由指定的 File對象表示的文件。
  • public FileOutputStream(String name, boolean append): 創(chuàng)建文件輸出流以指定的名稱寫入文件脊髓。

這兩個構造方法辫愉,參數中都需要傳入一個boolean類型的值,true 表示追加數據将硝,false 表示清空原有數據恭朗。這樣創(chuàng)建的輸出流對象,就可以指定是否追加續(xù)寫了依疼,代碼使用演示:

public class FOSWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名稱創(chuàng)建流對象
        FileOutputStream fos = new FileOutputStream("fos.txt"痰腮,true);     
        // 字符串轉換為字節(jié)數組
        byte[] b = "abcde".getBytes();
        // 寫出從索引2開始,2個字節(jié)律罢。索引2是c诽嘉,兩個字節(jié),也就是cd弟翘。
        fos.write(b);
        // 關閉資源
        fos.close();
    }
}
文件操作前:cd
文件操作后:cdabcde

寫出換行

代碼使用演示:

public class FOSWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名稱創(chuàng)建流對象
        FileOutputStream fos = new FileOutputStream("fos.txt");  
        // 定義字節(jié)數組
        byte[] words = {97,98,99,100,101};
        // 遍歷數組
        for (int i = 0; i < words.length; i++) {
            // 寫出一個字節(jié)
            fos.write(words[i]);
            // 寫出一個換行, 換行符號轉成數組寫出
            fos.write("\r\n".getBytes());
        }
        // 關閉資源
        fos.close();
    }
}

輸出結果:
a
b
c
d
e
  • 回車符\r和換行符\n
    • 回車符:回到一行的開頭(return)虫腋。
    • 換行符:下一行(newline)。
  • 系統(tǒng)中的換行:
    • Windows系統(tǒng)里稀余,每行結尾是 回車+換行 悦冀,即\r\n
    • Unix系統(tǒng)里睛琳,每行結尾只有 換行 盒蟆,即\n踏烙;
    • Mac系統(tǒng)里,每行結尾是 回車 历等,即\r讨惩。從 Mac OS X開始與Linux統(tǒng)一。

2.4 字節(jié)輸入流【InputStream】

java.io.InputStream抽象類是表示字節(jié)輸入流的所有類的超類寒屯,可以讀取字節(jié)信息到內存中荐捻。它定義了字節(jié)輸入流的基本共性功能方法。

  • public void close() :關閉此輸入流并釋放與此流相關聯(lián)的任何系統(tǒng)資源寡夹。
  • public abstract int read(): 從輸入流讀取數據的下一個字節(jié)处面。
  • public int read(byte[] b): 從輸入流中讀取一些字節(jié)數,并將它們存儲到字節(jié)數組 b中 菩掏。

小貼士:

close方法魂角,當完成流的操作時,必須調用此方法智绸,釋放系統(tǒng)資源野揪。

2.5 FileInputStream類

java.io.FileInputStream類是文件輸入流,從文件中讀取字節(jié)瞧栗。

構造方法

  • FileInputStream(File file): 通過打開與實際文件的連接來創(chuàng)建一個 FileInputStream 囱挑,該文件由文件系統(tǒng)中的 File對象 file命名。
  • FileInputStream(String name): 通過打開與實際文件的連接來創(chuàng)建一個 FileInputStream 沼溜,該文件由文件系統(tǒng)中的路徑名 name命名平挑。

當你創(chuàng)建一個流對象時,必須傳入一個文件路徑系草。該路徑下通熄,如果沒有該文件,會拋出FileNotFoundException

  • 構造舉例找都,代碼如下:
public class FileInputStreamConstructor throws IOException{
    public static void main(String[] args) {
        // 使用File對象創(chuàng)建流對象
        File file = new File("a.txt");
        FileInputStream fos = new FileInputStream(file);
      
        // 使用文件名稱創(chuàng)建流對象
        FileInputStream fos = new FileInputStream("b.txt");
    }
}

讀取字節(jié)數據

字節(jié)輸入流的使用步驟:
1 創(chuàng)建FileInputStream對象唇辨,構造方法中綁定要讀取的數據源。
2 使用FileInputStream對象中的read方法能耻,讀取文件
3 釋放資源赏枚。

  1. 讀取字節(jié)read方法,每次可以讀取一個字節(jié)的數據晓猛,提升為int類型饿幅,讀取到文件末尾,返回-1戒职,代碼使用演示:
public class FISRead {
    public static void main(String[] args) throws IOException{
        // 使用文件名稱創(chuàng)建流對象
        FileInputStream fis = new FileInputStream("read.txt");
        // 讀取數據栗恩,返回一個字節(jié)
        int read = fis.read();
        System.out.println((char) read);
        read = fis.read();
        System.out.println((char) read);
        read = fis.read();
        System.out.println((char) read);
        read = fis.read();
        System.out.println((char) read);
        read = fis.read();
        System.out.println((char) read);
        // 讀取到末尾,返回-1
        read = fis.read();
        System.out.println( read);
        // 關閉資源
        fis.close();
    }
}
輸出結果:
a
b
c
d
e
-1

循環(huán)改進讀取方式,代碼使用演示:

public class FISRead {
    public static void main(String[] args) throws IOException{
        // 使用文件名稱創(chuàng)建流對象
        FileInputStream fis = new FileInputStream("read.txt");
        // 定義變量洪燥,保存數據
        int b 磕秤;
        // 循環(huán)讀取
        while ((b = fis.read())!=-1) {
            System.out.println((char)b);
        }
        // 關閉資源
        fis.close();
    }
}
輸出結果:
a
b
c
d
e

小貼士:

  1. 雖然讀取了一個字節(jié)乳乌,但是會自動提升為int類型。
  2. 流操作完畢后市咆,必須釋放系統(tǒng)資源汉操,調用close方法,千萬記得蒙兰。
  1. 使用字節(jié)數組讀取read(byte[] b)磷瘤,每次讀取b的長度個字節(jié)到數組中,返回讀取到的有效字節(jié)個數癞己,讀取到末尾時,返回-1 梭伐,代碼使用演示:
public class FISRead {
    public static void main(String[] args) throws IOException{
        // 使用文件名稱創(chuàng)建流對象.
        FileInputStream fis = new FileInputStream("read.txt"); // 文件中為abcde
        // 定義變量痹雅,作為有效個數
        int len ;
        // 定義字節(jié)數組糊识,作為裝字節(jié)數據的容器   
        byte[] b = new byte[2];
        // 循環(huán)讀取
        while (( len= fis.read(b))!=-1) {
            // 每次讀取后,把數組變成字符串打印
            System.out.println(new String(b));
        }
        // 關閉資源
        fis.close();
    }
}

輸出結果:
ab
cd
ed

錯誤數據d绩社,是由于最后一次讀取時,只讀取一個字節(jié)e赂苗,數組中愉耙,上次讀取的數據沒有被完全替換,所以要通過len 拌滋,獲取有效的字節(jié)朴沿,代碼使用演示:

public class FISRead {
    public static void main(String[] args) throws IOException{
        // 使用文件名稱創(chuàng)建流對象.
        FileInputStream fis = new FileInputStream("read.txt"); // 文件中為abcde
        // 定義變量,作為有效個數
        int len 败砂;
        // 定義字節(jié)數組赌渣,作為裝字節(jié)數據的容器   
        byte[] b = new byte[2];
        // 循環(huán)讀取
        while (( len= fis.read(b))!=-1) {
            // 每次讀取后,把數組的有效字節(jié)部分,變成字符串打印
            System.out.println(new String(b昌犹,0坚芜,len));//  len 每次讀取的有效字節(jié)個數
        }
        // 關閉資源
        fis.close();
    }
}

輸出結果:
ab
cd
e

小貼士:

使用數組讀取,每次讀取多個字節(jié)斜姥,減少了系統(tǒng)間的IO操作次數鸿竖,從而提高了讀寫的效率,建議開發(fā)中使用铸敏。

2.6 字節(jié)流練習:圖片復制

復制原理圖解

案例實現

復制圖片文件缚忧,代碼使用演示:

public class Copy {
    public static void main(String[] args) throws IOException {
        // 1.創(chuàng)建流對象
        // 1.1 指定數據源
        FileInputStream fis = new FileInputStream("D:\\test.jpg");
        // 1.2 指定目的地
        FileOutputStream fos = new FileOutputStream("test_copy.jpg");

        // 2.讀寫數據
        // 2.1 定義數組
        byte[] b = new byte[1024];
        // 2.2 定義長度
        int len;
        // 2.3 循環(huán)讀取
        while ((len = fis.read(b))!=-1) {
            // 2.4 寫出數據
            fos.write(b, 0 , len);
        }

        // 3.關閉資源
        fos.close();
        fis.close();
    }
}

小貼士:

流的關閉原則:先開后關,后開先關杈笔。

第三章 字符流

當使用字節(jié)流讀取文本文件時搔谴,可能會有一個小問題。就是遇到中文字符時桩撮,可能不會顯示完整的字符敦第,那是因為一個中文字符可能占用多個字節(jié)存儲峰弹。所以Java提供一些字符流類,以字符為單位讀寫數據芜果,專門用于處理文本文件鞠呈。
使用字節(jié)流讀取中文文件時:
1個中文:
在GBK中占用2個字節(jié)。
在UTF-8中占用3個字節(jié)右钾。

3.1 字符輸入流【Reader】

java.io.Reader抽象類是表示用于讀取字符流的所有類的超類蚁吝,可以讀取字符信息到內存中。它定義了字符輸入流的基本共性功能方法舀射。

  • public void close() :關閉此流并釋放與此流相關聯(lián)的任何系統(tǒng)資源窘茁。
  • public int read(): 從輸入流讀取一個字符。
  • public int read(char[] cbuf): 從輸入流中讀取一些字符脆烟,并將它們存儲到字符數組 cbuf中 山林。

3.2 FileReader類

java.io.FileReader類是讀取字符文件的便利類。構造時使用系統(tǒng)默認的字符編碼和默認字節(jié)緩沖區(qū)邢羔。

小貼士:

  1. 字符編碼:字節(jié)與字符的對應規(guī)則驼抹。Windows系統(tǒng)的中文編碼默認是GBK編碼表。

    idea中UTF-8

  2. 字節(jié)緩沖區(qū):一個字節(jié)數組拜鹤,用來臨時存儲字節(jié)數據框冀。

構造方法

  • FileReader(File file): 創(chuàng)建一個新的 FileReader ,給定要讀取的File對象敏簿。
  • FileReader(String fileName): 創(chuàng)建一個新的 FileReader 明也,給定要讀取的文件的名稱。

當你創(chuàng)建一個流對象時惯裕,必須傳入一個文件路徑诡右。類似于FileInputStream 。

  • 構造舉例轻猖,代碼如下:
public class FileReaderConstructor throws IOException{
    public static void main(String[] args) {
        // 使用File對象創(chuàng)建流對象
        File file = new File("a.txt");
        FileReader fr = new FileReader(file);
      
        // 使用文件名稱創(chuàng)建流對象
        FileReader fr = new FileReader("b.txt");
    }
}

讀取字符數據

  1. 讀取字符read方法帆吻,每次可以讀取一個字符的數據,提升為int類型咙边,讀取到文件末尾猜煮,返回-1,循環(huán)讀取败许,代碼使用演示:
public class FRRead {
    public static void main(String[] args) throws IOException {
        // 使用文件名稱創(chuàng)建流對象
        FileReader fr = new FileReader("read.txt");
        // 定義變量王带,保存數據
        int b ;
        // 循環(huán)讀取
        while ((b = fr.read())!=-1) {
            System.out.println((char)b);
        }
        // 關閉資源
        fr.close();
    }
}
輸出結果:
黑
馬
程
序
員

小貼士:雖然讀取了一個字符市殷,但是會自動提升為int類型愕撰。

  1. 使用字符數組讀取read(char[] cbuf),每次讀取b的長度個字符到數組中,返回讀取到的有效字符個數搞挣,讀取到末尾時带迟,返回-1 ,代碼使用演示:
public class FRRead {
    public static void main(String[] args) throws IOException {
        // 使用文件名稱創(chuàng)建流對象
        FileReader fr = new FileReader("read.txt");
        // 定義變量囱桨,保存有效字符個數
        int len 仓犬;
        // 定義字符數組,作為裝字符數據的容器
         char[] cbuf = new char[2];
        // 循環(huán)讀取
        while ((len = fr.read(cbuf))!=-1) {
            System.out.println(new String(cbuf));
        }
        // 關閉資源
        fr.close();
    }
}
輸出結果:
黑馬
程序
員序

獲取有效的字符改進舍肠,代碼使用演示:

public class FISRead {
    public static void main(String[] args) throws IOException {
        // 使用文件名稱創(chuàng)建流對象
        FileReader fr = new FileReader("read.txt");
        // 定義變量搀继,保存有效字符個數
        int len ;
        // 定義字符數組翠语,作為裝字符數據的容器
        char[] cbuf = new char[2];
        // 循環(huán)讀取
        while ((len = fr.read(cbuf))!=-1) {
            System.out.println(new String(cbuf,0,len));
        }
        // 關閉資源
        fr.close();
    }
}

輸出結果:
黑馬
程序
員

3.3 字符輸出流【Writer】

java.io.Writer抽象類是表示用于寫出字符流的所有類的超類叽躯,將指定的字符信息寫出到目的地。它定義了字節(jié)輸出流的基本共性功能方法肌括。

  • void write(int c) 寫入單個字符点骑。
  • void write(char[] cbuf)寫入字符數組。
  • abstract void write(char[] cbuf, int off, int len)寫入字符數組的某一部分,off數組的開始索引,len寫的字符個數们童。
  • void write(String str)寫入字符串畔况。
  • void write(String str, int off, int len) 寫入字符串的某一部分,off字符串的開始索引,len寫的字符個數鲸鹦。
  • void flush()刷新該流的緩沖慧库。
  • void close() 關閉此流,但要先刷新它馋嗜。

3.4 FileWriter類

java.io.FileWriter類是寫出字符到文件的便利類齐板。構造時使用系統(tǒng)默認的字符編碼和默認字節(jié)緩沖區(qū)。

構造方法

  • FileWriter(File file): 創(chuàng)建一個新的 FileWriter葛菇,給定要讀取的File對象甘磨。
  • FileWriter(String fileName): 創(chuàng)建一個新的 FileWriter,給定要讀取的文件的名稱眯停。

當你創(chuàng)建一個流對象時济舆,必須傳入一個文件路徑,類似于FileOutputStream莺债。

  • 構造舉例滋觉,代碼如下:
public class FileWriterConstructor {
    public static void main(String[] args) throws IOException {
        // 使用File對象創(chuàng)建流對象
        File file = new File("a.txt");
        FileWriter fw = new FileWriter(file);
      
        // 使用文件名稱創(chuàng)建流對象
        FileWriter fw = new FileWriter("b.txt");
    }
}

基本寫出數據

寫出字符write(int b) 方法,每次可以寫出一個字符數據齐邦,代碼使用演示:

public class FWWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名稱創(chuàng)建流對象
        FileWriter fw = new FileWriter("fw.txt");     
        // 寫出數據
        fw.write(97); // 寫出第1個字符
        fw.write('b'); // 寫出第2個字符
        fw.write('C'); // 寫出第3個字符
        fw.write(30000); // 寫出第4個字符椎侠,中文編碼表中30000對應一個漢字。
      
        /*
        【注意】關閉資源時,與FileOutputStream不同措拇。
         如果不關閉,數據只是保存到緩沖區(qū)我纪,并未保存到文件。
        */
        // fw.close();
    }
}
輸出結果:
abC田

小貼士:

  1. 雖然參數為int類型四個字節(jié),但是只會保留一個字符的信息寫出浅悉。
  2. 未調用close方法趟据,數據只是保存到了緩沖區(qū),并未寫出到文件中仇冯。

關閉和刷新

因為內置緩沖區(qū)的原因之宿,如果不關閉輸出流,無法寫出字符到文件中苛坚。但是關閉的流對象比被,是無法繼續(xù)寫出數據的。如果我們既想寫出數據泼舱,又想繼續(xù)使用流等缀,就需要flush 方法了。

  • flush :刷新緩沖區(qū)娇昙,流對象可以繼續(xù)使用尺迂。
  • close:先刷新緩沖區(qū),然后通知系統(tǒng)釋放資源冒掌。流對象不可以再被使用了噪裕。

代碼使用演示:

public class FWWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名稱創(chuàng)建流對象
        FileWriter fw = new FileWriter("fw.txt");
        // 寫出數據,通過flush
        fw.write('刷'); // 寫出第1個字符
        fw.flush();
        fw.write('新'); // 繼續(xù)寫出第2個字符股毫,寫出成功
        fw.flush();
      
        // 寫出數據膳音,通過close
        fw.write('關'); // 寫出第1個字符
        fw.close();
        fw.write('閉'); // 繼續(xù)寫出第2個字符,【報錯】java.io.IOException: Stream closed
        fw.close();
    }
}

小貼士:即便是flush方法寫出了數據,操作的最后還是要調用close方法铃诬,釋放系統(tǒng)資源祭陷。

寫出其他數據

  1. 寫出字符數組write(char[] cbuf)write(char[] cbuf, int off, int len) ,每次可以寫出字符數組中的數據趣席,用法類似FileOutputStream兵志,代碼使用演示:
public class FWWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名稱創(chuàng)建流對象
        FileWriter fw = new FileWriter("fw.txt");     
        // 字符串轉換為字節(jié)數組
        char[] chars = "我是程序員".toCharArray();
      
        // 寫出字符數組
        fw.write(chars); // 我是程序員
        
        // 寫出從索引2開始,2個字節(jié)宣肚。索引2是'程'想罕,兩個字節(jié),也就是'程序'霉涨。
        fw.write(b,2,2); // 程序
      
        // 關閉資源
        fos.close();
    }
}
  1. 寫出字符串write(String str)write(String str, int off, int len) 按价,每次可以寫出字符串中的數據,更為方便嵌纲,代碼使用演示:
public class FWWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名稱創(chuàng)建流對象
        FileWriter fw = new FileWriter("fw.txt");     
        // 字符串
        String msg = "我是程序員";
      
        // 寫出字符數組
        fw.write(msg); //我是程序員
      
        // 寫出從索引2開始俘枫,2個字節(jié)。索引2是'程'逮走,兩個字節(jié)鸠蚪,也就是'程序'。
        fw.write(msg,2,2);  // 程序
        
        // 關閉資源
        fos.close();
    }
}
  1. 續(xù)寫和換行:操作類似于FileOutputStream。
public class FWWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名稱創(chuàng)建流對象茅信,可以續(xù)寫數據
        FileWriter fw = new FileWriter("fw.txt"盾舌,true);     
        // 寫出字符串
        fw.write("我是");
        // 寫出換行
        fw.write("\r\n");
        // 寫出字符串
        fw.write("程序員");
        // 關閉資源
        fw.close();
    }
}
輸出結果:
我是
程序員

小貼士:字符流,只能操作文本文件蘸鲸,不能操作圖片妖谴,視頻等非文本文件。

當我們單純讀或者寫文本文件時 使用字符流 其他情況使用字節(jié)流

第四章 IO異常的處理

JDK7前處理

之前的入門練習酌摇,我們一直把異常拋出膝舅,而實際開發(fā)中并不能這樣處理,建議使用try...catch...finally 代碼塊窑多,處理異常部分仍稀,代碼使用演示:

public class HandleException1 {
    public static void main(String[] args) {
        // 聲明變量
        FileWriter fw = null;
        try {
            //創(chuàng)建流對象
            fw = new FileWriter("fw.txt");
            // 寫出數據
            fw.write("我是程序員"); //我是程序員
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fw != null) {
                    fw.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

JDK7的處理(擴展知識點了解內容)

還可以使用JDK7優(yōu)化后的try-with-resource 語句,該語句確保了每個資源在語句結束時關閉埂息。所謂的資源(resource)是指在程序完成后技潘,必須關閉的對象。

格式:

try (創(chuàng)建流對象語句千康,如果多個,使用';'隔開) {
    // 讀寫數據
} catch (IOException e) {
    e.printStackTrace();
}

代碼使用演示:

public class HandleException2 {
    public static void main(String[] args) {
        // 創(chuàng)建流對象
        try ( FileWriter fw = new FileWriter("fw.txt"); ) {
            // 寫出數據
            fw.write("黑馬程序員"); //黑馬程序員
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

JDK9的改進(擴展知識點了解內容)

JDK9中try-with-resource 的改進享幽,對于引入對象的方式,支持的更加簡潔拾弃。被引入的對象值桩,同樣可以自動關閉,無需手動close砸彬,我們來了解一下格式颠毙。

改進前格式:

// 被final修飾的對象
final Resource resource1 = new Resource("resource1");
// 普通對象
Resource resource2 = new Resource("resource2");
// 引入方式:創(chuàng)建新的變量保存
try (Resource r1 = resource1;
     Resource r2 = resource2) {
     // 使用對象
}

改進后格式:

// 被final修飾的對象
final Resource resource1 = new Resource("resource1");
// 普通對象
Resource resource2 = new Resource("resource2");

// 引入方式:直接引入
try (resource1; resource2) {
     // 使用對象
}

改進后斯入,代碼使用演示:

public class TryDemo {
    public static void main(String[] args) throws IOException {
        // 創(chuàng)建流對象
        final  FileReader fr  = new FileReader("in.txt");
        FileWriter fw = new FileWriter("out.txt");
        // 引入到try中
        try (fr; fw) {
            // 定義變量
            int b;
            // 讀取數據
            while ((b = fr.read())!=-1) {
                // 寫出數據
                fw.write(b);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

第五章 屬性集

5.1 概述

java.util.Properties 繼承于Hashtable 砂碉,來表示一個持久的屬性集。它使用鍵值結構存儲數據刻两,每個鍵及其對應值都是一個字符串增蹭。該類也被許多Java類使用,比如獲取系統(tǒng)屬性時磅摹,System.getProperties 方法就是返回一個Properties對象滋迈。

5.2 Properties類

Properties集合是唯一一個和IO流相結合的集合。
1 可以使用Properties集合中的方法store把集合中的臨時數據持久化到硬盤中存儲户誓。
2 可以使用Properties集合中的方法load,把硬盤中保存的文件(鍵值對)讀取到集合中使用饼灿。

Properties集合是一個雙列集合 key和value默認是字符串。

構造方法

  • public Properties() :創(chuàng)建一個空的屬性列表帝美。

基本的存儲方法

  • public Object setProperty(String key, String value) : 保存一對屬性碍彭。
  • public String getProperty(String key) :使用此屬性列表中指定的鍵搜索屬性值。
  • public Set<String> stringPropertyNames() :所有鍵的名稱的集合。
public class ProDemo {
    public static void main(String[] args) throws FileNotFoundException {
        // 創(chuàng)建屬性集對象
        Properties properties = new Properties();
        // 添加鍵值對元素
        properties.setProperty("filename", "a.txt");
        properties.setProperty("length", "209385038");
        properties.setProperty("location", "D:\\a.txt");
        // 打印屬性集對象
        System.out.println(properties);
        // 通過鍵,獲取屬性值
        System.out.println(properties.getProperty("filename"));
        System.out.println(properties.getProperty("length"));
        System.out.println(properties.getProperty("location"));

        // 遍歷屬性集,獲取所有鍵的集合
        Set<String> strings = properties.stringPropertyNames();
        // 打印鍵值對
        for (String key : strings ) {
            System.out.println(key+" -- "+properties.getProperty(key));
        }
    }
}
輸出結果:
{filename=a.txt, length=209385038, location=D:\a.txt}
a.txt
209385038
D:\a.txt
filename -- a.txt
length -- 209385038
location -- D:\a.txt

與流相關的方法

  • public void load(InputStream inStream): 從字節(jié)輸入流中讀取鍵值對庇忌。

參數中使用了字節(jié)輸入流舞箍,通過流對象,可以關聯(lián)到某文件上皆疹,這樣就能夠加載文本中的數據了疏橄。文本數據格式:

filename=a.txt
length=209385038
location=D:\a.txt

加載代碼演示:

public class ProDemo2 {
    public static void main(String[] args) throws FileNotFoundException {
        // 創(chuàng)建屬性集對象
        Properties pro = new Properties();
        // 加載文本中信息到屬性集
        pro.load(new FileInputStream("read.txt"));
        // 遍歷集合并打印
        Set<String> strings = pro.stringPropertyNames();
        for (String key : strings ) {
            System.out.println(key+" -- "+pro.getProperty(key));
        }
     }
}
輸出結果:
filename -- a.txt
length -- 209385038
location -- D:\a.txt

小貼士:文本中的數據,必須是鍵值對形式略就,可以使用空格捎迫、等號、冒號等符號分隔表牢。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末立砸,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子初茶,更是在濱河造成了極大的恐慌颗祝,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件恼布,死亡現場離奇詭異螺戳,居然都是意外死亡,警方通過查閱死者的電腦和手機折汞,發(fā)現死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進店門倔幼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人爽待,你說我怎么就攤上這事损同。” “怎么了鸟款?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵膏燃,是天一觀的道長。 經常有香客問我何什,道長组哩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任处渣,我火速辦了婚禮伶贰,結果婚禮上,老公的妹妹穿的比我還像新娘罐栈。我一直安慰自己黍衙,他們只是感情好,可當我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布荠诬。 她就那樣靜靜地躺著琅翻,像睡著了一般涯捻。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上望迎,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天障癌,我揣著相機與錄音,去河邊找鬼辩尊。 笑死涛浙,一個胖子當著我的面吹牛,可吹牛的內容都是我干的摄欲。 我是一名探鬼主播轿亮,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼胸墙!你這毒婦竟也來了我注?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤迟隅,失蹤者是張志新(化名)和其女友劉穎但骨,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體智袭,經...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡奔缠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了吼野。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片校哎。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖瞳步,靈堂內的尸體忽然破棺而出闷哆,到底是詐尸還是另有隱情,我是刑警寧澤单起,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布抱怔,位于F島的核電站,受9級特大地震影響馏臭,放射性物質發(fā)生泄漏野蝇。R本人自食惡果不足惜讼稚,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一括儒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧锐想,春花似錦帮寻、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽浅蚪。三九已至,卻和暖如春烫罩,著一層夾襖步出監(jiān)牢的瞬間惜傲,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工贝攒, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留盗誊,地道東北人。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓隘弊,卻偏偏與公主長得像哈踱,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子梨熙,可洞房花燭夜當晚...
    茶點故事閱讀 45,086評論 2 355

推薦閱讀更多精彩內容