字節(jié)流 字符流

第一章 IO概述

1.1 什么是IO

生活中晌端,你肯定經(jīng)歷過這樣的場(chǎng)景。當(dāng)你編輯一個(gè)文本文件婉陷,忘記了ctrl+s 帚称,可能文件就白白編輯了。當(dāng)你電腦上插入一個(gè)U盤秽澳,可以把一個(gè)視頻闯睹,拷貝到你的電腦硬盤里。那么數(shù)據(jù)都是在哪些設(shè)備上的呢担神?鍵盤楼吃、內(nèi)存、硬盤妄讯、外接設(shè)備等等孩锡。

我們把這種數(shù)據(jù)的傳輸,可以看做是一種數(shù)據(jù)的流動(dòng)亥贸,按照流動(dòng)的方向躬窜,以內(nèi)存為基準(zhǔn),分為輸入input輸出output 炕置,即流向內(nèi)存是輸入流斩披,流出內(nèi)存的輸出流。

Java中I/O操作主要是指使用java.io包下的內(nèi)容讹俊,進(jìn)行輸入、輸出操作煌抒。輸入也叫做讀取數(shù)據(jù)仍劈,輸出也叫做作寫出數(shù)據(jù)。

1.2 IO的分類

根據(jù)數(shù)據(jù)的流向分為:輸入流輸出流寡壮。

  • 輸入流 :把數(shù)據(jù)從其他設(shè)備上讀取到內(nèi)存中的流贩疙。
  • 輸出流 :把數(shù)據(jù)從內(nèi)存 中寫出到其他設(shè)備上的流讹弯。

格局?jǐn)?shù)據(jù)的類型分為:字節(jié)流字符流

  • 字節(jié)流 :以字節(jié)為單位这溅,讀寫數(shù)據(jù)的流组民。
  • 字符流 :以字符為單位,讀寫數(shù)據(jù)的流悲靴。

1.3 IO的流向說明圖解

[圖片上傳失敗...(image-6f3339-1603349770263)]

1.4 頂級(jí)父類們

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

第二章 字節(jié)流

2.1 一切皆為字節(jié)

一切文件數(shù)據(jù)(文本臭胜、圖片、視頻等)在存儲(chǔ)時(shí)癞尚,都是以二進(jìn)制數(shù)字的形式保存耸三,都一個(gè)一個(gè)的字節(jié),那么傳輸時(shí)一樣如此浇揩。所以仪壮,字節(jié)流可以傳輸任意文件數(shù)據(jù)。在操作流的時(shí)候胳徽,我們要時(shí)刻明確积锅,無論使用什么樣的流對(duì)象,底層傳輸?shù)氖冀K為二進(jìn)制數(shù)據(jù)养盗。

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

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

  • public void close() :關(guān)閉此輸出流并釋放與此流相關(guān)聯(lián)的任何系統(tǒng)資源蹬跃。
  • public void flush() :刷新此輸出流并強(qiáng)制任何緩沖的輸出字節(jié)被寫出。
  • public void write(byte[] b):將 b.length字節(jié)從指定的字節(jié)數(shù)組寫入此輸出流铆铆。
  • public void write(byte[] b, int off, int len) :從指定的字節(jié)數(shù)組寫入 len字節(jié)蝶缀,從偏移量 off開始輸出到此輸出流。
  • public abstract void write(int b) :將指定的字節(jié)輸出流薄货。

小貼士:

close方法翁都,當(dāng)完成流的操作時(shí),必須調(diào)用此方法谅猾,釋放系統(tǒng)資源柄慰。

2.3 FileOutputStream類

OutputStream有很多子類,我們從最簡(jiǎn)單的一個(gè)子類開始税娜。

java.io.FileOutputStream類是文件輸出流坐搔,用于將數(shù)據(jù)寫出到文件。

構(gòu)造方法

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

當(dāng)你創(chuàng)建一個(gè)流對(duì)象時(shí),必須傳入一個(gè)文件路徑弧岳。該路徑下凳忙,如果沒有這個(gè)文件业踏,會(huì)創(chuàng)建該文件。如果有這個(gè)文件涧卵,會(huì)清空這個(gè)文件的數(shù)據(jù)勤家。

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

寫出字節(jié)數(shù)據(jù)

  1. 寫出字節(jié)write(int b) 方法柳恐,每次可以寫出一個(gè)字節(jié)數(shù)據(jù)伐脖,代碼使用演示:
public class FOSWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名稱創(chuàng)建流對(duì)象
        FileOutputStream fos = new FileOutputStream("fos.txt");     
        // 寫出數(shù)據(jù)
        fos.write(97); // 寫出第1個(gè)字節(jié)
        fos.write(98); // 寫出第2個(gè)字節(jié)
        fos.write(99); // 寫出第3個(gè)字節(jié)
        // 關(guān)閉資源
        fos.close();
    }
}
輸出結(jié)果:
abc

小貼士:

  1. 雖然參數(shù)為int類型四個(gè)字節(jié),但是只會(huì)保留一個(gè)字節(jié)的信息寫出胎撤。
  2. 流操作完畢后晓殊,必須釋放系統(tǒng)資源,調(diào)用close方法伤提,千萬記得巫俺。
  1. 寫出字節(jié)數(shù)組write(byte[] b),每次可以寫出數(shù)組中的數(shù)據(jù)肿男,代碼使用演示:
public class FOSWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名稱創(chuàng)建流對(duì)象
        FileOutputStream fos = new FileOutputStream("fos.txt");     
        // 字符串轉(zhuǎn)換為字節(jié)數(shù)組
        byte[] b = "黑馬程序員".getBytes();
        // 寫出字節(jié)數(shù)組數(shù)據(jù)
        fos.write(b);
        // 關(guān)閉資源
        fos.close();
    }
}
輸出結(jié)果:
黑馬程序員
  1. 寫出指定長(zhǎng)度字節(jié)數(shù)組write(byte[] b, int off, int len) ,每次寫出從off索引開始介汹,len個(gè)字節(jié),代碼使用演示:
public class FOSWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名稱創(chuàng)建流對(duì)象
        FileOutputStream fos = new FileOutputStream("fos.txt");     
        // 字符串轉(zhuǎn)換為字節(jié)數(shù)組
        byte[] b = "abcde".getBytes();
        // 寫出從索引2開始舶沛,2個(gè)字節(jié)嘹承。索引2是c,兩個(gè)字節(jié)如庭,也就是cd叹卷。
        fos.write(b,2,2);
        // 關(guān)閉資源
        fos.close();
    }
}
輸出結(jié)果:
cd

數(shù)據(jù)追加續(xù)寫

經(jīng)過以上的演示,每次程序運(yùn)行坪它,創(chuàng)建輸出流對(duì)象骤竹,都會(huì)清空目標(biāo)文件中的數(shù)據(jù)。如何保留目標(biāo)文件中數(shù)據(jù)往毡,還能繼續(xù)添加新數(shù)據(jù)呢蒙揣?

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

這兩個(gè)構(gòu)造方法懒震,參數(shù)中都需要傳入一個(gè)boolean類型的值,true 表示追加數(shù)據(jù)嗤详,false 表示清空原有數(shù)據(jù)个扰。這樣創(chuàng)建的輸出流對(duì)象龄毡,就可以指定是否追加續(xù)寫了渣淤,代碼使用演示:

public class FOSWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名稱創(chuàng)建流對(duì)象
        FileOutputStream fos = new FileOutputStream("fos.txt"中燥,true);     
        // 字符串轉(zhuǎn)換為字節(jié)數(shù)組
        byte[] b = "abcde".getBytes();
        // 寫出從索引2開始知给,2個(gè)字節(jié)杈笔。索引2是c浅碾,兩個(gè)字節(jié)夹囚,也就是cd部念。
        fos.write(b);
        // 關(guān)閉資源
        fos.close();
    }
}
文件操作前:cd
文件操作后:cdabcde

寫出換行

Windows系統(tǒng)里舞痰,換行符號(hào)是\r\n 土榴。把

以指定是否追加續(xù)寫了,代碼使用演示:

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

輸出結(jié)果:
a
b
c
d
e
  • 回車符\r和換行符\n
    • 回車符:回到一行的開頭(return)响牛。
    • 換行符:下一行(newline)玷禽。
  • 系統(tǒng)中的換行:
    • Windows系統(tǒng)里,每行結(jié)尾是 回車+換行 呀打,即\r\n矢赁;
    • Unix系統(tǒng)里,每行結(jié)尾只有 換行 贬丛,即\n撩银;
    • Mac系統(tǒng)里,每行結(jié)尾是 回車 豺憔,即\r额获。從 Mac OS X開始與Linux統(tǒng)一。

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

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

  • public void close() :關(guān)閉此輸入流并釋放與此流相關(guān)聯(lián)的任何系統(tǒng)資源昼榛。
  • public abstract int read(): 從輸入流讀取數(shù)據(jù)的下一個(gè)字節(jié)境肾。
  • public int read(byte[] b): 從輸入流中讀取一些字節(jié)數(shù),并將它們存儲(chǔ)到字節(jié)數(shù)組 b中 胆屿。

小貼士:

close方法奥喻,當(dāng)完成流的操作時(shí),必須調(diào)用此方法莺掠,釋放系統(tǒng)資源衫嵌。

2.5 FileInputStream類

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

構(gòu)造方法

  • FileInputStream(File file): 通過打開與實(shí)際文件的連接來創(chuàng)建一個(gè) FileInputStream 楔绞,該文件由文件系統(tǒng)中的 File對(duì)象 file命名。
  • FileInputStream(String name): 通過打開與實(shí)際文件的連接來創(chuàng)建一個(gè) FileInputStream 唇兑,該文件由文件系統(tǒng)中的路徑名 name命名酒朵。

當(dāng)你創(chuàng)建一個(gè)流對(duì)象時(shí),必須傳入一個(gè)文件路徑扎附。該路徑下蔫耽,如果沒有該文件,會(huì)拋出FileNotFoundException

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

讀取字節(jié)數(shù)據(jù)

  1. 讀取字節(jié)read方法匙铡,每次可以讀取一個(gè)字節(jié)的數(shù)據(jù)图甜,提升為int類型,讀取到文件末尾鳖眼,返回-1黑毅,代碼使用演示:
public class FISRead {
    public static void main(String[] args) throws IOException{
        // 使用文件名稱創(chuàng)建流對(duì)象
        FileInputStream fis = new FileInputStream("read.txt");
        // 讀取數(shù)據(jù),返回一個(gè)字節(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);
        // 關(guān)閉資源
        fis.close();
    }
}
輸出結(jié)果:
a
b
c
d
e
-1

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

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

小貼士:

  1. 雖然讀取了一個(gè)字節(jié)愿卒,但是會(huì)自動(dòng)提升為int類型缚去。
  2. 流操作完畢后,必須釋放系統(tǒng)資源琼开,調(diào)用close方法易结,千萬記得。
  1. 使用字節(jié)數(shù)組讀取read(byte[] b)稠通,每次讀取b的長(zhǎng)度個(gè)字節(jié)到數(shù)組中衬衬,返回讀取到的有效字節(jié)個(gè)數(shù),讀取到末尾時(shí)改橘,返回-1 滋尉,代碼使用演示:
public class FISRead {
    public static void main(String[] args) throws IOException{
        // 使用文件名稱創(chuàng)建流對(duì)象.
        FileInputStream fis = new FileInputStream("read.txt"); // 文件中為abcde
        // 定義變量,作為有效個(gè)數(shù)
        int len 飞主;
        // 定義字節(jié)數(shù)組狮惜,作為裝字節(jié)數(shù)據(jù)的容器   
        byte[] b = new byte[2];
        // 循環(huán)讀取
        while (( len= fis.read(b))!=-1) {
            // 每次讀取后,把數(shù)組變成字符串打印
            System.out.println(new String(b));
        }
        // 關(guān)閉資源
        fis.close();
    }
}

輸出結(jié)果:
ab
cd
ed

錯(cuò)誤數(shù)據(jù)d,是由于最后一次讀取時(shí)碌识,只讀取一個(gè)字節(jié)e碾篡,數(shù)組中,上次讀取的數(shù)據(jù)沒有被完全替換筏餐,所以要通過len 开泽,獲取有效的字節(jié),代碼使用演示:

public class FISRead {
    public static void main(String[] args) throws IOException{
        // 使用文件名稱創(chuàng)建流對(duì)象.
        FileInputStream fis = new FileInputStream("read.txt"); // 文件中為abcde
        // 定義變量魁瞪,作為有效個(gè)數(shù)
        int len 穆律;
        // 定義字節(jié)數(shù)組,作為裝字節(jié)數(shù)據(jù)的容器   
        byte[] b = new byte[2];
        // 循環(huán)讀取
        while (( len= fis.read(b))!=-1) {
            // 每次讀取后,把數(shù)組的有效字節(jié)部分导俘,變成字符串打印
            System.out.println(new String(b峦耘,0,len));//  len 每次讀取的有效字節(jié)個(gè)數(shù)
        }
        // 關(guān)閉資源
        fis.close();
    }
}

輸出結(jié)果:
ab
cd
e

小貼士:

使用數(shù)組讀取旅薄,每次讀取多個(gè)字節(jié)辅髓,減少了系統(tǒng)間的IO操作次數(shù),從而提高了讀寫的效率,建議開發(fā)中使用洛口。

2.6 字節(jié)流練習(xí):圖片復(fù)制

復(fù)制原理圖解

[圖片上傳失敗...(image-9d5c8c-1603349770264)]

案例實(shí)現(xiàn)

復(fù)制圖片文件矫付,代碼使用演示:

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

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

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

小貼士:

流的關(guān)閉原則:先開后關(guān),后開先關(guān)绍弟。

第三章 字符流

當(dāng)使用字節(jié)流讀取文本文件時(shí)技即,可能會(huì)有一個(gè)小問題。就是遇到中文字符時(shí)樟遣,可能不會(huì)顯示完整的字符,那是因?yàn)橐粋€(gè)中文字符可能占用多個(gè)字節(jié)存儲(chǔ)身笤。所以Java提供一些字符流類豹悬,以字符為單位讀寫數(shù)據(jù),專門用于處理文本文件液荸。

3.1 字符輸入流【Reader】

java.io.Reader抽象類是表示用于讀取字符流的所有類的超類瞻佛,可以讀取字符信息到內(nèi)存中。它定義了字符輸入流的基本共性功能方法娇钱。

  • public void close() :關(guān)閉此流并釋放與此流相關(guān)聯(lián)的任何系統(tǒng)資源伤柄。
  • public int read(): 從輸入流讀取一個(gè)字符。
  • public int read(char[] cbuf): 從輸入流中讀取一些字符文搂,并將它們存儲(chǔ)到字符數(shù)組 cbuf中 适刀。

3.2 FileReader類

java.io.FileReader類是讀取字符文件的便利類。構(gòu)造時(shí)使用系統(tǒng)默認(rèn)的字符編碼和默認(rèn)字節(jié)緩沖區(qū)煤蹭。

小貼士:

  1. 字符編碼:字節(jié)與字符的對(duì)應(yīng)規(guī)則笔喉。Windows系統(tǒng)的中文編碼默認(rèn)是GBK編碼表。

    idea中UTF-8

  2. 字節(jié)緩沖區(qū):一個(gè)字節(jié)數(shù)組硝皂,用來臨時(shí)存儲(chǔ)字節(jié)數(shù)據(jù)常挚。

構(gòu)造方法

  • FileReader(File file): 創(chuàng)建一個(gè)新的 FileReader ,給定要讀取的File對(duì)象稽物。
  • FileReader(String fileName): 創(chuàng)建一個(gè)新的 FileReader 奄毡,給定要讀取的文件的名稱。

當(dāng)你創(chuàng)建一個(gè)流對(duì)象時(shí)贝或,必須傳入一個(gè)文件路徑吼过。類似于FileInputStream 。

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

讀取字符數(shù)據(jù)

  1. 讀取字符read方法那先,每次可以讀取一個(gè)字符的數(shù)據(jù),提升為int類型赡艰,讀取到文件末尾售淡,返回-1,循環(huán)讀取,代碼使用演示:
public class FRRead {
    public static void main(String[] args) throws IOException {
        // 使用文件名稱創(chuàng)建流對(duì)象
        FileReader fr = new FileReader("read.txt");
        // 定義變量揖闸,保存數(shù)據(jù)
        int b 揍堕;
        // 循環(huán)讀取
        while ((b = fr.read())!=-1) {
            System.out.println((char)b);
        }
        // 關(guān)閉資源
        fr.close();
    }
}
輸出結(jié)果:
黑
馬
程
序
員

小貼士:雖然讀取了一個(gè)字符,但是會(huì)自動(dòng)提升為int類型汤纸。

  1. 使用字符數(shù)組讀取read(char[] cbuf)衩茸,每次讀取b的長(zhǎng)度個(gè)字符到數(shù)組中,返回讀取到的有效字符個(gè)數(shù)贮泞,讀取到末尾時(shí)楞慈,返回-1 ,代碼使用演示:
public class FRRead {
    public static void main(String[] args) throws IOException {
        // 使用文件名稱創(chuàng)建流對(duì)象
        FileReader fr = new FileReader("read.txt");
        // 定義變量啃擦,保存有效字符個(gè)數(shù)
        int len 囊蓝;
        // 定義字符數(shù)組,作為裝字符數(shù)據(jù)的容器
         char[] cbuf = new char[2];
        // 循環(huán)讀取
        while ((len = fr.read(cbuf))!=-1) {
            System.out.println(new String(cbuf));
        }
        // 關(guān)閉資源
        fr.close();
    }
}
輸出結(jié)果:
黑馬
程序
員序

獲取有效的字符改進(jìn)令蛉,代碼使用演示:

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

輸出結(jié)果:
黑馬
程序
員

3.3 字符輸出流【W(wǎng)riter】

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

  • void write(int c) 寫入單個(gè)字符姥芥。
  • void write(char[] cbuf)寫入字符數(shù)組。
  • abstract void write(char[] cbuf, int off, int len)寫入字符數(shù)組的某一部分,off數(shù)組的開始索引,len寫的字符個(gè)數(shù)辆憔。
  • void write(String str)寫入字符串撇眯。
  • void write(String str, int off, int len) 寫入字符串的某一部分,off字符串的開始索引,len寫的字符個(gè)數(shù)。
  • void flush()刷新該流的緩沖虱咧。
  • void close() 關(guān)閉此流熊榛,但要先刷新它。

3.4 FileWriter類

java.io.FileWriter類是寫出字符到文件的便利類腕巡。構(gòu)造時(shí)使用系統(tǒng)默認(rèn)的字符編碼和默認(rèn)字節(jié)緩沖區(qū)玄坦。

構(gòu)造方法

  • FileWriter(File file): 創(chuàng)建一個(gè)新的 FileWriter,給定要讀取的File對(duì)象绘沉。
  • FileWriter(String fileName): 創(chuàng)建一個(gè)新的 FileWriter煎楣,給定要讀取的文件的名稱。

當(dāng)你創(chuàng)建一個(gè)流對(duì)象時(shí)车伞,必須傳入一個(gè)文件路徑择懂,類似于FileOutputStream。

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

基本寫出數(shù)據(jù)

寫出字符write(int b) 方法困曙,每次可以寫出一個(gè)字符數(shù)據(jù)表伦,代碼使用演示:

public class FWWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名稱創(chuàng)建流對(duì)象
        FileWriter fw = new FileWriter("fw.txt");     
        // 寫出數(shù)據(jù)
        fw.write(97); // 寫出第1個(gè)字符
        fw.write('b'); // 寫出第2個(gè)字符
        fw.write('C'); // 寫出第3個(gè)字符
        fw.write(30000); // 寫出第4個(gè)字符,中文編碼表中30000對(duì)應(yīng)一個(gè)漢字慷丽。
      
        /*
        【注意】關(guān)閉資源時(shí),與FileOutputStream不同蹦哼。
         如果不關(guān)閉,數(shù)據(jù)只是保存到緩沖區(qū),并未保存到文件要糊。
        */
        // fw.close();
    }
}
輸出結(jié)果:
abC田

小貼士:

  1. 雖然參數(shù)為int類型四個(gè)字節(jié)纲熏,但是只會(huì)保留一個(gè)字符的信息寫出。
  2. 未調(diào)用close方法锄俄,數(shù)據(jù)只是保存到了緩沖區(qū)局劲,并未寫出到文件中。

關(guān)閉和刷新

因?yàn)閮?nèi)置緩沖區(qū)的原因奶赠,如果不關(guān)閉輸出流容握,無法寫出字符到文件中。但是關(guān)閉的流對(duì)象车柠,是無法繼續(xù)寫出數(shù)據(jù)的。如果我們既想寫出數(shù)據(jù)塑猖,又想繼續(xù)使用流竹祷,就需要flush 方法了。

  • flush :刷新緩沖區(qū)羊苟,流對(duì)象可以繼續(xù)使用塑陵。
  • close:先刷新緩沖區(qū),然后通知系統(tǒng)釋放資源蜡励。流對(duì)象不可以再被使用了令花。

代碼使用演示:

public class FWWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名稱創(chuàng)建流對(duì)象
        FileWriter fw = new FileWriter("fw.txt");
        // 寫出數(shù)據(jù),通過flush
        fw.write('刷'); // 寫出第1個(gè)字符
        fw.flush();
        fw.write('新'); // 繼續(xù)寫出第2個(gè)字符凉倚,寫出成功
        fw.flush();
      
        // 寫出數(shù)據(jù)兼都,通過close
        fw.write('關(guān)'); // 寫出第1個(gè)字符
        fw.close();
        fw.write('閉'); // 繼續(xù)寫出第2個(gè)字符,【報(bào)錯(cuò)】java.io.IOException: Stream closed
        fw.close();
    }
}

小貼士:即便是flush方法寫出了數(shù)據(jù),操作的最后還是要調(diào)用close方法稽寒,釋放系統(tǒng)資源扮碧。

寫出其他數(shù)據(jù)

  1. 寫出字符數(shù)組write(char[] cbuf)write(char[] cbuf, int off, int len) ,每次可以寫出字符數(shù)組中的數(shù)據(jù)杏糙,用法類似FileOutputStream慎王,代碼使用演示:
public class FWWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名稱創(chuàng)建流對(duì)象
        FileWriter fw = new FileWriter("fw.txt");     
        // 字符串轉(zhuǎn)換為字節(jié)數(shù)組
        char[] chars = "黑馬程序員".toCharArray();
      
        // 寫出字符數(shù)組
        fw.write(chars); // 黑馬程序員
        
        // 寫出從索引2開始,2個(gè)字節(jié)宏侍。索引2是'程'赖淤,兩個(gè)字節(jié),也就是'程序'谅河。
        fw.write(b,2,2); // 程序
      
        // 關(guān)閉資源
        fos.close();
    }
}
  1. 寫出字符串write(String str)write(String str, int off, int len) 咱旱,每次可以寫出字符串中的數(shù)據(jù)确丢,更為方便,代碼使用演示:
public class FWWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名稱創(chuàng)建流對(duì)象
        FileWriter fw = new FileWriter("fw.txt");     
        // 字符串
        String msg = "黑馬程序員";
      
        // 寫出字符數(shù)組
        fw.write(msg); //黑馬程序員
      
        // 寫出從索引2開始莽龟,2個(gè)字節(jié)蠕嫁。索引2是'程',兩個(gè)字節(jié)毯盈,也就是'程序'剃毒。
        fw.write(msg,2,2);  // 程序
        
        // 關(guān)閉資源
        fos.close();
    }
}
  1. 續(xù)寫和換行:操作類似于FileOutputStream。
public class FWWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名稱創(chuàng)建流對(duì)象搂赋,可以續(xù)寫數(shù)據(jù)
        FileWriter fw = new FileWriter("fw.txt"赘阀,true);     
        // 寫出字符串
        fw.write("黑馬");
        // 寫出換行
        fw.write("\r\n");
        // 寫出字符串
        fw.write("程序員");
        // 關(guān)閉資源
        fw.close();
    }
}
輸出結(jié)果:
黑馬
程序員

小貼士:字符流,只能操作文本文件脑奠,不能操作圖片基公,視頻等非文本文件。

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

第四章 IO異常的處理

JDK7前處理

之前的入門練習(xí)宋欺,我們一直把異常拋出轰豆,而實(shí)際開發(fā)中并不能這樣處理,建議使用try...catch...finally 代碼塊齿诞,處理異常部分酸休,代碼使用演示:

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

JDK7的處理(擴(kuò)展知識(shí)點(diǎn)了解內(nèi)容)

還可以使用JDK7優(yōu)化后的try-with-resource 語(yǔ)句,該語(yǔ)句確保了每個(gè)資源在語(yǔ)句結(jié)束時(shí)關(guān)閉祷杈。所謂的資源(resource)是指在程序完成后斑司,必須關(guān)閉的對(duì)象。

格式:

try (創(chuàng)建流對(duì)象語(yǔ)句但汞,如果多個(gè),使用';'隔開) {
    // 讀寫數(shù)據(jù)
} catch (IOException e) {
    e.printStackTrace();
}

代碼使用演示:

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

JDK9的改進(jìn)(擴(kuò)展知識(shí)點(diǎn)了解內(nèi)容)

JDK9中try-with-resource 的改進(jìn)宿刮,對(duì)于引入對(duì)象的方式,支持的更加簡(jiǎn)潔私蕾。被引入的對(duì)象僵缺,同樣可以自動(dòng)關(guān)閉,無需手動(dòng)close是目,我們來了解一下格式谤饭。

改進(jìn)前格式:

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

改進(jìn)后格式:

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

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

改進(jìn)后,代碼使用演示:

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

第五章 屬性集

5.1 概述

java.util.Properties 繼承于Hashtable 懊纳,來表示一個(gè)持久的屬性集揉抵。它使用鍵值結(jié)構(gòu)存儲(chǔ)數(shù)據(jù),每個(gè)鍵及其對(duì)應(yīng)值都是一個(gè)字符串嗤疯。該類也被許多Java類使用冤今,比如獲取系統(tǒng)屬性時(shí),System.getProperties 方法就是返回一個(gè)Properties對(duì)象茂缚。

5.2 Properties類

構(gòu)造方法

  • public Properties() :創(chuàng)建一個(gè)空的屬性列表戏罢。

基本的存儲(chǔ)方法

  • public Object setProperty(String key, String value) : 保存一對(duì)屬性屋谭。
  • public String getProperty(String key) :使用此屬性列表中指定的鍵搜索屬性值。
  • public Set<String> stringPropertyNames() :所有鍵的名稱的集合龟糕。
public class ProDemo {
    public static void main(String[] args) throws FileNotFoundException {
        // 創(chuàng)建屬性集對(duì)象
        Properties properties = new Properties();
        // 添加鍵值對(duì)元素
        properties.setProperty("filename", "a.txt");
        properties.setProperty("length", "209385038");
        properties.setProperty("location", "D:\\a.txt");
        // 打印屬性集對(duì)象
        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();
        // 打印鍵值對(duì)
        for (String key : strings ) {
            System.out.println(key+" -- "+properties.getProperty(key));
        }
    }
}
輸出結(jié)果:
{filename=a.txt, length=209385038, location=D:\a.txt}
a.txt
209385038
D:\a.txt
filename -- a.txt
length -- 209385038
location -- D:\a.txt

與流相關(guān)的方法

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

參數(shù)中使用了字節(jié)輸入流,通過流對(duì)象讲岁,可以關(guān)聯(lián)到某文件上我擂,這樣就能夠加載文本中的數(shù)據(jù)了。文本數(shù)據(jù)格式:

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

加載代碼演示:

public class ProDemo2 {
    public static void main(String[] args) throws FileNotFoundException {
        // 創(chuàng)建屬性集對(duì)象
        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));
        }
     }
}
輸出結(jié)果:
filename -- a.txt
length -- 209385038
location -- D:\a.txt

小貼士:文本中的數(shù)據(jù)缓艳,必須是鍵值對(duì)形式校摩,可以使用空格、等號(hào)阶淘、冒號(hào)等符號(hào)分隔衙吩。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市溪窒,隨后出現(xiàn)的幾起案子坤塞,更是在濱河造成了極大的恐慌,老刑警劉巖澈蚌,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件尺锚,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡惜浅,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門伏嗜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來坛悉,“玉大人,你說我怎么就攤上這事承绸÷阌埃” “怎么了?”我有些...
    開封第一講書人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵军熏,是天一觀的道長(zhǎng)轩猩。 經(jīng)常有香客問我,道長(zhǎng)荡澎,這世上最難降的妖魔是什么均践? 我笑而不...
    開封第一講書人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮摩幔,結(jié)果婚禮上彤委,老公的妹妹穿的比我還像新娘。我一直安慰自己或衡,他們只是感情好焦影,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開白布车遂。 她就那樣靜靜地躺著,像睡著了一般斯辰。 火紅的嫁衣襯著肌膚如雪舶担。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,718評(píng)論 1 305
  • 那天彬呻,我揣著相機(jī)與錄音衣陶,去河邊找鬼。 笑死废岂,一個(gè)胖子當(dāng)著我的面吹牛祖搓,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播湖苞,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼拯欧,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了财骨?” 一聲冷哼從身側(cè)響起镐作,我...
    開封第一講書人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎隆箩,沒想到半個(gè)月后该贾,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡捌臊,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年杨蛋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片理澎。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡逞力,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出糠爬,到底是詐尸還是另有隱情寇荧,我是刑警寧澤,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布执隧,位于F島的核電站揩抡,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏镀琉。R本人自食惡果不足惜峦嗤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望屋摔。 院中可真熱鬧寻仗,春花似錦、人聲如沸凡壤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至曹体,卻和暖如春俗扇,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背箕别。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工铜幽, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人串稀。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓除抛,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親母截。 傳聞我的和親對(duì)象是個(gè)殘疾皇子到忽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355