Java IO流(二)

IO流常用基類

字節(jié)流的抽象基類:
InputStream
OutputStream
字符流的抽象基類:

Reader
Writer
注意:由這四個(gè)類派生出來的子類名稱都是以其父類名作為子類名的后綴的。例如穆咐,InputStream的子類——FileInputStream元扔,Reader的子類——FileReader。

字節(jié)流

字節(jié)流的基本操作與字符流類同派阱,但它不僅可以操作字符株扛,還可以操作其他媒體文件护姆。這里,我列出比較常用的字節(jié)流先较,如下:

FileInputStream
FileOutputStream
BufferedInputStream
BufferedOutputStream
字節(jié)輸出流——FileOutputStream

首先我為讀者介紹一下字節(jié)輸出流——FileOutputStream携冤。以一個(gè)例子來作為我的開場(chǎng)白。
例闲勺,向一個(gè)文本文件中寫入數(shù)據(jù)曾棕。
這里我使用字節(jié)輸出流——FileOutputStream向一個(gè)文本文件中寫入數(shù)據(jù),此處直接給出示例代碼菜循。

public class FileOutputStreamDemo {

public static void main(String[] args) throws IOException {
    /*
     * 將數(shù)據(jù)寫入到文件中翘地。
     * 使用字節(jié)輸出流。
     * FileOutputStream癌幕。
     */

    File dir = new File("tempfile");
    if (!dir.exists()) {
        dir.mkdir();
    }

    // 1衙耕、創(chuàng)建字節(jié)輸出流對(duì)象,用于操作文件勺远,在對(duì)象初始化時(shí)必須明確數(shù)據(jù)存儲(chǔ)的目的地橙喘。
    // 輸出流所關(guān)聯(lián)的目的地,如果不存在胶逢,會(huì)自動(dòng)創(chuàng)建厅瞎。如果存在饰潜,則覆蓋。
    FileOutputStream fos = new FileOutputStream("tempfile\\fos.txt");

    // 2和簸、調(diào)用輸出流的寫功能彭雾。

// String str = "abcde";
// byte[] buf = str.getBytes();
fos.write("abcde".getBytes());

    // 3、釋放資源锁保。
    fos.close();
}

}

這里我們須注意一點(diǎn)——?jiǎng)?chuàng)建字節(jié)輸出流對(duì)象用于操作文件冠跷,在對(duì)象初始化時(shí)必須明確數(shù)據(jù)存儲(chǔ)的目的地,輸出流所關(guān)聯(lián)的目的地身诺,如果不存在,則會(huì)自動(dòng)創(chuàng)建抄囚;如果存在霉赡,則會(huì)覆蓋。

對(duì)IOException的處理方式

在使用字節(jié)輸出流——FileOutputStream向一個(gè)文本文件中寫入數(shù)據(jù)時(shí)幔托,就不可避免地發(fā)生IOException異常穴亏,對(duì)該異常的正確處理方式究竟是怎樣的呢?下面已給出重挑。

public class IOExceptionDemo {

public static void main(String[] args) {

    FileOutputStream fos = null;

    try {
        fos = new FileOutputStream("tempfile\\fos.txt");
        fos.write("hello".getBytes());
    } catch (IOException e) {

        // 自處理.... 但通常將異常信息寫入到日志文件中以進(jìn)行記錄嗓化。
        System.out.println(e.toString() + "----------------");
    } finally {
        if (fos != null) // 放在try代碼塊里面亦可
            try {
                fos.close();
            } catch (IOException e) {
                // 一般可以throw RuntimeException異常,或者將異常信息寫入到日志文件中以進(jìn)行記錄谬哀。
                throw new RuntimeException("關(guān)閉失敗" + e);
            }
    }


}

}

注意:最后無論如何都應(yīng)關(guān)閉資源刺覆,所以應(yīng)放在finally代碼塊中。以后在對(duì)IO流的操作中史煎,出現(xiàn)IOException異常谦屑,就按照上述代碼進(jìn)行處理。

字節(jié)輸出流的續(xù)寫和換行

現(xiàn)在思考這樣一個(gè)問題:如果想在原有文件上繼續(xù)加入新的數(shù)據(jù)篇梭,咋整呢氢橙?很簡(jiǎn)單,創(chuàng)建一個(gè)FileOutputStream對(duì)象時(shí)恬偷,傳遞一個(gè)true參數(shù)悍手,代表不覆蓋已有的文件,即在已有文件的末尾處進(jìn)行數(shù)據(jù)續(xù)寫袍患。示例代碼如下:

public class IOExceptionDemo {

private static final String LINE_SEPARATOR = System.getProperty("line.separator");

public static void main(String[] args) {

    FileOutputStream fos = null;

    try {
        fos = new FileOutputStream("tempfile\\fos.txt", true); // 傳入true實(shí)現(xiàn)續(xù)寫坦康。

        String str = LINE_SEPARATOR + "hello";

        fos.write(str.getBytes());

    } catch (IOException e) {

        // 自處理....
        System.out.println(e.toString() + "----------------");
    } finally {
        if (fos != null) 
            try {
                fos.close();
            } catch (IOException e) {

                throw new RuntimeException("關(guān)閉失敗" + e);
            }
    }

}

}

注意:\r\n在Windows中表示行終止符,但在其他系統(tǒng)中并不是這樣协怒,所以為了更加通用涝焙,使用System類的getProperty(“l(fā)ine.separator”)方法得到系統(tǒng)的行終止符。

字節(jié)輸入流——FileInputStream

我們知道如何使用字節(jié)輸出流——FileOutputStream向一個(gè)文本文件中寫入數(shù)據(jù)之后孕暇,就要考慮將已有文件的數(shù)據(jù)讀取出來仑撞。
現(xiàn)在就有這樣一個(gè)需求:從硬盤的一個(gè)文件中讀取內(nèi)容赤兴。
分析:既然是讀取文件,顯然要使用InputStream隧哮,而且又因?yàn)槭且僮魑募傲迹宰罱K應(yīng)使用FileInputStream。使用字節(jié)輸入流——FileInputStream讀取文件有三種方式沮翔,下面我會(huì)詳述這三種方式陨帆。
首先使用第一種方式來讀取文件,給出示例代碼如下采蚀,以供讀者參考疲牵。

public class FileInputStreamDemo {

public static void main(String[] args) throws IOException {

    // 為了確保文件一定在讀之前是存在的,將字符串路徑封裝成File對(duì)象榆鼠。
    File file = new File("tempfile\\fos.txt");
    if (!(file.exists())) {
        throw new RuntimeException("要讀取的文件不存在");
    }

    // 創(chuàng)建文件字節(jié)讀取流對(duì)象時(shí)纲爸,必須明確與之關(guān)聯(lián)的數(shù)據(jù)源。
    FileInputStream fis = new FileInputStream(file);

    // 調(diào)用讀取流對(duì)象的讀方法妆够。read();
    int by = 0;
    while ((by = fis.read()) != -1) {
        System.out.println(by);
    }

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

}

我覺得總有初學(xué)者對(duì)以上程序代碼感到一頭霧水的识啦,但是沒關(guān)系啦!下面我就會(huì)畫一張圖來解釋其原理神妹,圖畫的糙颓哮,還請(qǐng)讀者諒解。
這里寫圖片描述
接下來就使用第二種方式來讀取文件鸵荠,同樣給出示例代碼如下(其中加入了對(duì)IOException異常的處理)冕茅,以供讀者參考。

public class FileInputStreamDemo2 {

private static final int DEFAULT_SIZE = 1024; // 緩沖區(qū)大小可以是1024的整數(shù)倍蛹找。

public static void main(String[] args) {

    // 演示第二種讀取方式嵌赠,read(byte[]);
    FileInputStream fis = null;

    try {
        fis = new FileInputStream("tempfile\\fos.txt");

        // 創(chuàng)建一個(gè)字節(jié)數(shù)組。
        byte[] buf = new byte[DEFAULT_SIZE];

        int len = 0;
        // 調(diào)用read(byte[])方法
        while ((len = fis.read(buf)) != -1) { // len記錄的是往字節(jié)數(shù)組里存儲(chǔ)的字節(jié)個(gè)數(shù)熄赡。
            System.out.println(new String(buf, 0, len)); // 將字節(jié)數(shù)組轉(zhuǎn)成字符串姜挺,打印并看一下效果。
        }
    } catch (IOException e) {
        // 將異常信息寫入到日志文件中以進(jìn)行記錄彼硫。
    } finally {
        if (fis != null) {
            try {
                fis.close();
            } catch (IOException e) {
                // 一般可以throw RuntimeException異常炊豪,或者將異常信息寫入到日志文件中以進(jìn)行記錄。
                e.printStackTrace();
            }
        }
    }
}

}

從以上程序代碼中拧篮,可知在創(chuàng)建緩沖區(qū)(一個(gè)字節(jié)數(shù)組)時(shí)词渤,緩沖區(qū)的大小一般設(shè)置為1024的整數(shù)倍。同上串绩,下面我畫一張糙圖來解釋上述程序代碼缺虐。
這里寫圖片描述
最后,使用第三種方式來讀取文件礁凡,給出示例代碼如下高氮,供讀者參考慧妄。

public class FileInputStreamDemo3 {

public static void main(String[] args) throws IOException {

    FileInputStream fis = new FileInputStream("tempfile\\fos.txt");

    System.out.println(fis.available()); // 獲取與之關(guān)聯(lián)的文件的字節(jié)數(shù)。
    byte[] buf = new byte[fis.available()]; // 定義一個(gè)剛剛好的緩沖區(qū)剪芍,不用再循環(huán)了塞淹。不過慎用!W锕饱普!
    fis.read(buf);
    String s = new String(buf);
    System.out.println(s);

    fis.close();

}

}

注意:不建議使用這種方式,因?yàn)榭赡軙?huì)有內(nèi)存溢出異常状共。

復(fù)制文本文件

現(xiàn)在有這樣一個(gè)需求:復(fù)制一個(gè)文本文件套耕。為了解決這個(gè)需求,首先就要分析一下破題思路峡继,復(fù)制文本文件說到底就是一個(gè)讀取源數(shù)據(jù)箍铲,并將數(shù)據(jù)寫到目的地的過程,由于要操作設(shè)備上的數(shù)據(jù)鬓椭,所以需要用到流,讀用到了輸入流关划,寫用到了輸出流小染,而且操作的還是文本文件,最終就需要用到字節(jié)流中操作文件的流對(duì)象了贮折。解決該需求其實(shí)有兩種方式裤翩,下面我會(huì)一一詳述這兩種方式。
首先使用第一種復(fù)制方式调榄,即從源數(shù)據(jù)中讀一個(gè)字節(jié)踊赠,就往目的地寫一個(gè)字節(jié)。下面給出示例代碼每庆,供讀者參考筐带。

public class CopyTextTest {

public static void main(String[] args) throws IOException {

    copyText();

}

public static void copyText() throws IOException {

    // 1、創(chuàng)建一個(gè)輸入流和源數(shù)據(jù)相關(guān)聯(lián)缤灵。
    FileInputStream fis = new FileInputStream("IO流.txt");

    // 2伦籍、創(chuàng)建一個(gè)輸出流,并通過輸出流創(chuàng)建一個(gè)目的地腮出。
    FileOutputStream fos = new FileOutputStream("tempfile\\io_copy.txt");

    // 3帖鸦、讀一個(gè),寫一個(gè)胚嘲。
    int by = 0;

    while ((by = fis.read()) != -1) {
        fos.write(by);
    }

    fos.close();
    fis.close();

}

}

接著再來看第二種復(fù)制方式作儿,同樣給出示例代碼如下。

public class CopyTextByBufTest {

public static void main(String[] args) {

    copyTextByBuf();

}

public static void copyTextByBuf() {

    FileInputStream fis = null;
    FileOutputStream fos = null;

    try {
        fis = new FileInputStream("IO流.txt");

        fos = new FileOutputStream("tempfile\\io_buf_copy.txt");

        // 創(chuàng)建一個(gè)緩沖區(qū)
        byte[] buf = new byte[1024];

        // 定義記錄個(gè)數(shù)的變量
        int len = 0;

        // 循環(huán)讀寫
        while ((len = fis.read(buf)) != -1) {

            fos.write(buf, 0, len);
        }
    } catch (IOException e) {

        // 異常日志馋劈。
    } finally {
        if (fos != null) {
            try {
                fos.close();
            } catch (IOException e) {
                // 異常日志攻锰。
                e.printStackTrace();
            }
        }
        if (fis != null) {
            try {
                fis.close();
            } catch (IOException e) {
                // 異常日志晾嘶。
                e.printStackTrace();
            }
        }
    }
}

}

相比第一種復(fù)制方式,此方式的復(fù)制效率會(huì)更高口注,所以建議使用第二種復(fù)制方式变擒。

字節(jié)流的緩沖區(qū)對(duì)象

現(xiàn)在有這樣一個(gè)需求:復(fù)制一個(gè)圖片。其解決思路如下:

用字節(jié)讀取流對(duì)象和圖片關(guān)聯(lián)寝志。
用字節(jié)寫入流對(duì)象創(chuàng)建一個(gè)圖片文件娇斑,用于存儲(chǔ)獲取到的圖片數(shù)據(jù)。
通過循環(huán)讀寫材部,完成數(shù)據(jù)的存儲(chǔ)毫缆。
關(guān)閉資源。
通過以上思路乐导,不難寫出如下代碼苦丁,程序代碼與復(fù)制一個(gè)文本文件非常相似。

import java.io.*;
class CopyPic {
public static void main(String[] args) {
FileOutputStream fos = null;
FileInputStream fis = null;
    try {
        fos = new FileOutputStream("c:\\2.jpg");
        fis = new FileInputStream("c:\\1.jpg");
        byte[] buf = new byte[1024];
        int len = 0;
        while((len=fis.read(buf)) != -1) {
        fos.write(buf, 0, len);
    }
        } catch(IOException e) {
        throw new RuntimeException("復(fù)制文件失敗");
        } finally {
        try {
        if(fis != null) 
        fis.close();
        } catch(IOException e) {
    throw new RuntimeException("讀取關(guān)閉失敗");
    }
        try {
        if(fos != null) 
        fos.close();
        } catch(IOException e) {
    throw new RuntimeException("寫入關(guān)閉失敗");
    }
    }
}
}

我覺得總有初學(xué)者對(duì)以上程序代碼感到一頭霧水的物臂,但是沒關(guān)系啦旺拉!下面我就會(huì)畫一張圖來解釋其原理,圖畫的糙棵磷,還請(qǐng)讀者諒解蛾狗。
這里寫圖片描述
復(fù)制一個(gè)圖片的需求解決完之后,接下來就要引出字節(jié)流的緩沖區(qū)對(duì)象了仪媒,它們分別是BufferedOutputStream和BufferedInputStream沉桌,它倆是怎樣使用的呢?下面同樣以復(fù)制一個(gè)圖片的案例來看看字節(jié)流的緩沖區(qū)對(duì)象到底是如何應(yīng)用在代碼中的算吩。

public class CopyPicByBufferDemo {

public static void main(String[] args) throws IOException {

    copyPicByBuffer();

}

public static void copyPicByBuffer() throws IOException {

    // 演示緩沖區(qū)留凭。
    // 1,創(chuàng)建具體的流對(duì)象偎巢。
    FileInputStream fis = new FileInputStream("tempfile\\1.jpg");
    // 對(duì)流進(jìn)行緩沖蔼夜。
    BufferedInputStream bufis = new BufferedInputStream(fis);

    FileOutputStream fos = new FileOutputStream("tempfile\\copy_1.jpg");
    BufferedOutputStream bufos = new BufferedOutputStream(fos);

    byte[] buf = new byte[1024];
    int len = 0;
    while ((len = bufis.read(buf)) != -1) { // 緩沖區(qū)的讀方法,從緩沖區(qū)里面讀出來的數(shù)據(jù)
        bufos.write(buf, 0, len); // 緩沖區(qū)的寫方法压昼,向緩沖區(qū)里面寫數(shù)據(jù)挎扰。
        bufos.flush(); // 刷新可有可無,因?yàn)榫彌_區(qū)滿了之后會(huì)自動(dòng)刷新巢音。
    }

    fos.close();
    fis.close();

}

}
轉(zhuǎn)載地址:https://blog.csdn.net/yerenyuan_pku/article/details/78231697

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末遵倦,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子官撼,更是在濱河造成了極大的恐慌梧躺,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,835評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異掠哥,居然都是意外死亡巩踏,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,900評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門续搀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來塞琼,“玉大人,你說我怎么就攤上這事禁舷”肷迹” “怎么了?”我有些...
    開封第一講書人閱讀 156,481評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵牵咙,是天一觀的道長(zhǎng)派近。 經(jīng)常有香客問我,道長(zhǎng)洁桌,這世上最難降的妖魔是什么渴丸? 我笑而不...
    開封第一講書人閱讀 56,303評(píng)論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮另凌,結(jié)果婚禮上谱轨,老公的妹妹穿的比我還像新娘。我一直安慰自己吠谢,他們只是感情好土童,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,375評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著囊卜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪错沃。 梳的紋絲不亂的頭發(fā)上栅组,一...
    開封第一講書人閱讀 49,729評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音枢析,去河邊找鬼玉掸。 笑死,一個(gè)胖子當(dāng)著我的面吹牛醒叁,可吹牛的內(nèi)容都是我干的司浪。 我是一名探鬼主播,決...
    沈念sama閱讀 38,877評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼把沼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼啊易!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起饮睬,我...
    開封第一講書人閱讀 37,633評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤租谈,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后捆愁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體割去,經(jīng)...
    沈念sama閱讀 44,088評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡窟却,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,443評(píng)論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了呻逆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片夸赫。...
    茶點(diǎn)故事閱讀 38,563評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖咖城,靈堂內(nèi)的尸體忽然破棺而出茬腿,到底是詐尸還是另有隱情,我是刑警寧澤酒繁,帶...
    沈念sama閱讀 34,251評(píng)論 4 328
  • 正文 年R本政府宣布滓彰,位于F島的核電站,受9級(jí)特大地震影響州袒,放射性物質(zhì)發(fā)生泄漏揭绑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,827評(píng)論 3 312
  • 文/蒙蒙 一郎哭、第九天 我趴在偏房一處隱蔽的房頂上張望他匪。 院中可真熱鬧,春花似錦夸研、人聲如沸邦蜜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,712評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽悼沈。三九已至,卻和暖如春姐扮,著一層夾襖步出監(jiān)牢的瞬間絮供,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,943評(píng)論 1 264
  • 我被黑心中介騙來泰國(guó)打工茶敏, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留壤靶,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,240評(píng)論 2 360
  • 正文 我出身青樓惊搏,卻偏偏與公主長(zhǎng)得像贮乳,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子恬惯,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,435評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容