Java IO之字節(jié)流和字符流

1 字節(jié)流

??在前面的學習過程中旦事,我們一直都是在操作文件或者文件夾,并沒有給文件中寫任何數(shù)據(jù)〖泵穑現(xiàn)在我們就要開始給文件中寫數(shù)據(jù)姐浮,或者讀取文件中的數(shù)據(jù)。

1.1 字節(jié)輸出流OutputStream

??OutputStream此抽象類葬馋,是表示輸出字節(jié)流的所有類的超類卖鲤。操作的數(shù)據(jù)都是字節(jié)肾扰,定義了輸出字節(jié)流的基本共性功能方法。
??輸出流中定義都是寫write方法蛋逾,如下圖:

1.1.1 FileOutputStream類

??OutputStream有很多子類集晚,其中子類FileOutputStream可用來寫入數(shù)據(jù)到文件。FileOutputStream類区匣,即文件輸出流偷拔,是用于將數(shù)據(jù)寫入 File的輸出流。

構(gòu)造方法

1.1.2 FileOutputStream類寫入數(shù)據(jù)到文件中

將數(shù)據(jù)寫到文件中

package com.qtw.api;

import java.io.FileOutputStream;
import java.io.IOException;

/*
* 字節(jié)輸出流
*   java.io.OutputStream所有字節(jié)輸出流的超類
*   作用:從java程序?qū)懗鑫募?*   字節(jié):這樣的流每次文件中的1個字節(jié)
*   寫任意文件
*
*   方法都是寫入的方法
*
* write(int b) 寫入1個字節(jié)
* write(byte[] b) 寫入字節(jié)數(shù)組
* write(byte[] b,int,int) 寫入字節(jié)數(shù)組沉颂,int 開始寫入的索引条摸,int寫幾個
* close()方法悦污,關閉流對象铸屉,釋放此次流相關的資源
*
* 流對象,操作文件的時候切端,自己不做彻坛,依賴操作系統(tǒng)
*
*FileOutputStream
*   寫入數(shù)據(jù)文件,學習父類方法踏枣,使用子類對象
*
*   子類的構(gòu)造方法:作用:綁定輸出的輸出源
*       參數(shù)
*           File   文件對象
*           String   字符串的文件名
*   流對象使用步驟:
*       1.創(chuàng)建流子類的對象昌屉,綁定數(shù)據(jù)源
*       2.調(diào)用對象的方法write()寫入
*       3.close釋放資源
*    流對象的構(gòu)造方法可以創(chuàng)建文件,如果文件存在直接覆蓋
* */
public class TestDemo {
    public static void main(String[] args) throws IOException{
        FileOutputStream fos = new FileOutputStream("e:\\test\\a.txt");
        //寫入1個字節(jié)
        fos.write(100);
        //關閉資源
        fos.close();

        //寫入字節(jié)數(shù)組
        FileOutputStream fos1 = new FileOutputStream("e:\\test\\b.txt");
        byte[] arr = {97,98,99,100};
        fos1.write(arr);
        //寫入字節(jié)數(shù)組的一部分
        fos1.write(arr,1,2);
        fos1.close();

        //寫入字符串的簡便方法
        FileOutputStream fos2 = new FileOutputStream("e:\\test\\c.txt");
        String s = "Hello World";
        fos2.write(s.getBytes());
        fos2.close();
    }
}

1.1.3 給文件中續(xù)寫和換行

??我們直接new FileOutputStream(file)這樣創(chuàng)建對象茵瀑,寫入數(shù)據(jù)间驮,會覆蓋原有的文件,那么我們想在原有的文件中續(xù)寫內(nèi)容怎么辦呢马昨?
??繼續(xù)查閱FileOutputStream的API竞帽。發(fā)現(xiàn)在FileOutputStream的構(gòu)造函數(shù)中,可以接受一個boolean類型的值鸿捧,如果值true屹篓,就會在文件末位繼續(xù)添加。
構(gòu)造方法

給文件中續(xù)寫數(shù)據(jù)和換行匙奴,代碼演示:

package com.qtw.api;

import java.io.FileOutputStream;
import java.io.File;
import java.io.IOException;

public class TestDemo {
    public static void main(String[] args) throws Exception {
        File file = new File("e:\\test\\a.txt");
        FileOutputStream fos = new FileOutputStream(file, true);
        String str = "\r\n"+"Message ok";
        fos.write(str.getBytes());
        fos.close();
    }
}

1.1.4 IO異常的處理

??在前面編寫代碼中都發(fā)生了IO的異常堆巧。我們在實際開發(fā)中,對異常時如何處理的泼菌,我們來演示一下谍肤。

package com.qtw.api;

import java.io.FileOutputStream;
import java.io.File;
import java.io.IOException;

public class TestDemo {
    public static void main(String[] args) {
        File file = new File("e:\\test\\a.txt");
        //定義FileOutputStream的引用
        FileOutputStream fos = null;
        try {
            //創(chuàng)建FileOutputStream對象
            fos = new FileOutputStream(file);
            //寫出數(shù)據(jù)
            fos.write("abcde".getBytes());
        } catch (IOException ex) {
            System.out.println(ex.toString());
            throw new RuntimeException("文件寫入失敗,重試");
        } finally {
            //一定要判斷fos是否為null哗伯,只有不為null時荒揣,才可以關閉資源
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    throw new RuntimeException("文件釋放資源失敗");
                }
            }
        }
    }
}

1.2 字節(jié)輸入流InputStream

??通過前面的學習,我們可以把內(nèi)存中的數(shù)據(jù)寫出到文件中笋颤,那如何想把內(nèi)存中的數(shù)據(jù)讀到內(nèi)存中乳附,我們通過InputStream可以實現(xiàn)内地。InputStream此抽象類,是表示字節(jié)輸入流的所有類的超類赋除。阱缓,定義了字節(jié)輸入流的基本共性功能方法。

int read():讀取一個字節(jié)并返回举农,沒有字節(jié)返回-1荆针。
int read(byte[]): 讀取一定量的字節(jié)數(shù),并存儲到字節(jié)數(shù)組中颁糟,返回讀取到的字節(jié)數(shù)航背,沒有字節(jié)返回-1。

1.2.1 FileInputStream類

??InputStream有很多子類棱貌,其中子類FileInputStream可用來讀取文件內(nèi)容玖媚。
??FileInputStream 從文件系統(tǒng)中的某個文件中獲得輸入字節(jié)。

構(gòu)造方法

1.2.2 FileInputStream類讀取數(shù)據(jù)read方法

在讀取文件中的數(shù)據(jù)時婚脱,調(diào)用read方法今魔,實現(xiàn)從文件中讀取數(shù)據(jù)

從文件中讀取數(shù)據(jù),代碼演示:

package com.qtw.api;

import java.io.FileInputStream;
import java.io.File;
import java.io.IOException;

public class TestDemo {
    public static void main(String[] args) throws IOException{
        File file = new File("e:\\test\\a.txt");
        //創(chuàng)建一個字節(jié)輸入流對象,必須明確數(shù)據(jù)源障贸,其實就是創(chuàng)建字節(jié)讀取流和數(shù)據(jù)源相關聯(lián)错森。
        FileInputStream fis = new FileInputStream(file);
        //讀取數(shù)據(jù)。使用 read();一次讀一個字節(jié)篮洁。
        int ch = 0;
        while((ch=fis.read())!=-1){
            System.out.println("ch="+(char)ch);
        }
        fis.close();
    }
}

1.2.3 FileInputStream類讀取數(shù)據(jù)read(byte[])方法

??在讀取文件中的數(shù)據(jù)時涩维,調(diào)用read方法,每次只能讀取一個袁波,太麻煩了瓦阐,于是我們可以定義數(shù)組作為臨時的存儲容器,這時可以調(diào)用重載的read方法锋叨,一次可以讀取多個字符垄分。

package com.qtw.api;

import java.io.FileInputStream;
import java.io.File;
import java.io.IOException;

public class TestDemo {
    public static void main(String[] args) throws IOException{
        /*
         * 演示第二個讀取方法, read(byte[]);
         */
        File file = new File("e:\\test\\a.txt");
        // 創(chuàng)建一個字節(jié)輸入流對象,必須明確數(shù)據(jù)源娃磺,其實就是創(chuàng)建字節(jié)讀取流和數(shù)據(jù)源相關聯(lián)薄湿。
        FileInputStream fis = new FileInputStream(file);
        //創(chuàng)建一個字節(jié)數(shù)組。
        byte[] buf = new byte[2];
        int len = 0;
        while((len=fis.read(buf))!=-1){
            System.out.println(new String(buf,0,len));
        }
        fis.close();
    }
}

1.3 字節(jié)流練習

??既然會了文件的讀和寫操作了偷卧,那么我們就要在這個基礎上進行更為復雜的操作豺瘤。使用讀寫操作完成文件的復制。

1.3.1 復制文件

??原理听诸;讀取一個已有的數(shù)據(jù)坐求,并將這些讀到的數(shù)據(jù)寫入到另一個文件中。

循環(huán)復制單個字符TestDemo.java

package com.qtw.api;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.File;
import java.io.IOException;

public class TestDemo {
    public static void main(String[] args) throws IOException{
        //1,明確源和目的晌梨。
        File srcFile = new File("e:\\test\\timg.jpg");
        File destFile = new File("e:\\test\\a.jpg");

        //2,明確字節(jié)流 輸入流和源相關聯(lián)桥嗤,輸出流和目的關聯(lián)须妻。
        FileInputStream fis = new FileInputStream(srcFile);
        FileOutputStream fos = new FileOutputStream(destFile);

        //3, 使用輸入流的讀取方法讀取字節(jié),并將字節(jié)寫入到目的中泛领。
        int ch = 0;
        while((ch=fis.read())!=-1){
            fos.write(ch);
        }
        //4,關閉資源荒吏。
        fos.close();
        fis.close();
    }
}

??上述代碼輸入流和輸出流之間是通過ch這個變量進行數(shù)據(jù)交換的。
??上述復制文件有個問題渊鞋,每次都從源文件讀取一個绰更,然后在寫到指定文件,接著再讀取一個字符锡宋,然后再寫一個儡湾,一直這樣下去。效率極低执俩。
復制任何文件都行徐钠,ex:QQ.exe,因為所有的程序本質(zhì)都是字節(jié)

1.3.2 緩沖數(shù)組方式復制文件

??上述代碼復制文件效率太低了奠滑,并且頻繁的從文件讀數(shù)據(jù)丹皱,和寫數(shù)據(jù)妒穴,能不能一次多把文件中多個數(shù)據(jù)都讀進內(nèi)容中宋税,然后在一次寫出去,這樣的速度一定會比前面代碼速度快讼油。

package com.qtw.api;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.File;
import java.io.IOException;

public class TestDemo {
    public static void main(String[] args) throws IOException{
        File srcFile = new File("e:\\test\\timg.jpg");
        File destFile = new File("e:\\test\\b.jpg");
        // 明確字節(jié)流 輸入流和源相關聯(lián)杰赛,輸出流和目的關聯(lián)。
        FileInputStream fis = new FileInputStream(srcFile);
        FileOutputStream fos = new FileOutputStream(destFile);
        //定義一個緩沖區(qū)矮台。
        byte[] buf = new byte[1024];
        int len = 0;
        while ((len = fis.read(buf)) != -1) {
            fos.write(buf, 0, len);// 將數(shù)組中的指定長度的數(shù)據(jù)寫入到輸出流中乏屯。
        }
        // 關閉資源。
        fos.close();
        fis.close();
    }
}

2 字符流

??經(jīng)過前面的學習瘦赫,我們基本掌握的文件的讀寫操作辰晕,在操作過程中字節(jié)流可以操作所有數(shù)據(jù),可是當我們操作的文件中有中文字符确虱,并且需要對中文字符做出處理時怎么辦呢含友?

2.1 字節(jié)流讀取字符的問題

通過以下程序讀取帶有中文件的文件

package com.qtw.api;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class TestDemo {
    public static void main(String[] args) throws IOException {
        //給文件中寫中文
        writeCNText();
        //讀取文件中的中文
        readCNText();
    }
    //讀取中文
    public static void readCNText() throws IOException {
        FileInputStream fis = new FileInputStream("e:\\test\\a.txt");
        int ch = 0;
        while((ch = fis.read())!=-1){
            System.out.println(ch);
        }
    }
    //寫中文
    public static void writeCNText() throws IOException {
        FileOutputStream fos = new FileOutputStream("e:\\test\\a.txt");
        fos.write("a北京歡迎你".getBytes());
        fos.close();
    }
}

??上面程序在讀取含有中文的文件時,我們并沒有看到具體的中文校辩,而是看到一些數(shù)字窘问,這是什么原因呢?既然看不到中文宜咒,那么我們?nèi)绾螌ζ渲械闹形淖鎏幚砟鼗莺眨恳鉀Q這個問題,我們必須研究下字符的編碼過程故黑。

2.2 字符輸入流Reader

??上述程序中我們讀取擁有中文的文件時儿咱,使用的字節(jié)流在讀取庭砍,那么我們讀取到的都是一個一個字節(jié)。只要把這些字節(jié)去查閱對應的編碼表混埠,就能夠得到與之對應的字符逗威。API中是否給我們已經(jīng)提供了讀取相應字符的功能流對象,Reader岔冀,讀取字符流的抽象超類凯旭。

read():讀取單個字符并返回
read(char[]):將數(shù)據(jù)讀取到數(shù)組中,并返回讀取的個數(shù)使套。

2.3.1 FileReader類

??查閱FileInputStream的API罐呼,發(fā)現(xiàn)FileInputStream 用于讀取諸如圖像數(shù)據(jù)之類的原始字節(jié)流。要讀取字符流侦高,請考慮使用 FileReader嫉柴。打開FileReader的API介紹。用來讀取字符文件的便捷類奉呛。此類的構(gòu)造方法假定默認字符編碼和默認字節(jié)緩沖區(qū)大小都是適當?shù)?/p>

構(gòu)造方法

2.2.2 FileReader讀取包含中文的文件

使用FileReader讀取包含中文的文件

package com.qtw.api;

import java.io.FileReader;
import java.io.IOException;

public class TestDemo {
    public static void main(String[] args) throws IOException {
        //讀取文件中的中文
        readCNText();
    }
    //讀取中文
    public static void readCNText() throws IOException {
        FileReader fr = new FileReader("e:\\test\\a.txt");
        int ch = 0;
        while((ch = fr.read())!=-1){
            //輸出的字符對應的編碼值
            System.out.println(ch);
            //輸出字符本身
            System.out.println((char)ch);
        }
    }
}

2.3 字符輸出流Writer

??既然有專門用于讀取字符的流對象计螺,那么肯定也有寫的字符流對象,查閱API瞧壮,發(fā)現(xiàn)有一個Writer類登馒,Writer是寫入字符流的抽象類。其中描述了相應的寫的動作咆槽。

2.3.1 FileWriter類

??查閱FileOutputStream的API陈轿,發(fā)現(xiàn)FileOutputStream 用于寫入諸如圖像數(shù)據(jù)之類的原始字節(jié)的流。要寫入字符流秦忿,請考慮使用 FileWriter麦射。打開FileWriter的API介紹。用來寫入字符文件的便捷類灯谣。此類的構(gòu)造方法假定默認字符編碼和默認字節(jié)緩沖區(qū)大小都是可接受的潜秋。
構(gòu)造方法

2.3.2 FileWriter寫入中文到文件中

寫入字符到文件中,先進行流的刷新胎许,再進行流的關閉峻呛。

package com.qtw.api;

import java.io.FileWriter;
import java.io.IOException;

public class TestDemo {
    public static void main(String[] args) throws IOException {
        //演示FileWriter 用于操作文件的便捷類。
        FileWriter fw = new FileWriter("e:\\test\\a.txt");
        fw.write("你好謝謝再見");//這些文字都要先編碼呐萨。都寫入到了流的緩沖區(qū)中杀饵。
        fw.flush();
        fw.close();

    }
}

2.4 flush()和close()的區(qū)別?

??flush():將流中的緩沖區(qū)緩沖的數(shù)據(jù)刷新到目的地中谬擦,刷新后切距,流還可以繼續(xù)使用。
??close():關閉資源惨远,但在關閉前會將緩沖區(qū)中的數(shù)據(jù)先刷新到目的地谜悟,否則丟失數(shù)據(jù)话肖,然后在關閉流。流不可以使用葡幸。如果寫入數(shù)據(jù)多最筒,一定要一邊寫一邊刷新,最后一次可以不刷新蔚叨,由close完成刷新并關閉床蜘。

2.5 字符流練習

2.5.1 復制文本文件

練習:復制文本文件。
思路:

  1. 既然是文本涉及編碼表蔑水。需要用字符流邢锯。
  2. 操作的是文件。涉及硬盤搀别。
  3. 有指定碼表嗎丹擎?沒有,默認就行歇父。
    操作的是文件蒂培,使用的 默認碼表。使用哪個字符流對象榜苫。直接使用字符流操作文件的便捷類护戳。FileReader FileWriter
public class CopyTextFileTest {
    public static void main(String[] args) throws IOException {
        copyTextFile();
    }
    public static void copyTextFile() throws IOException {
        //1,明確源和目的。
        FileReader fr = new FileReader("c:\\cn.txt");
        FileWriter fw = new FileWriter("c:\\copy.txt");
        //2,為了提高效率单刁。自定義緩沖區(qū)數(shù)組灸异。字符數(shù)組。
        char[] buf = new char[1024];
        int len = 0;
        while((len=fr.read(buf))!=-1){
            fw.write(buf,0,len);
        }
        /*2,循環(huán)讀寫操作羔飞。效率低。
        int ch = 0;
        while((ch=fr.read())!=-1){
            fw.write(ch);
        }
        */
        //3,關閉資源檐春。
        fw.close();
        fr.close();
    }
}

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末逻淌,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子疟暖,更是在濱河造成了極大的恐慌卡儒,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件俐巴,死亡現(xiàn)場離奇詭異骨望,居然都是意外死亡,警方通過查閱死者的電腦和手機欣舵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進店門擎鸠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人缘圈,你說我怎么就攤上這事劣光⊥嗖希” “怎么了?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵绢涡,是天一觀的道長牲剃。 經(jīng)常有香客問我,道長雄可,這世上最難降的妖魔是什么凿傅? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮数苫,結(jié)果婚禮上狭归,老公的妹妹穿的比我還像新娘。我一直安慰自己文判,他們只是感情好过椎,可當我...
    茶點故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著戏仓,像睡著了一般疚宇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上赏殃,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天敷待,我揣著相機與錄音,去河邊找鬼仁热。 笑死榜揖,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的抗蠢。 我是一名探鬼主播举哟,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼迅矛!你這毒婦竟也來了妨猩?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤秽褒,失蹤者是張志新(化名)和其女友劉穎壶硅,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體销斟,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡庐椒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了蚂踊。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片约谈。...
    茶點故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出窗宇,到底是詐尸還是另有隱情措伐,我是刑警寧澤,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布军俊,位于F島的核電站侥加,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏粪躬。R本人自食惡果不足惜担败,卻給世界環(huán)境...
    茶點故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望镰官。 院中可真熱鬧提前,春花似錦、人聲如沸泳唠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽笨腥。三九已至拓哺,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間脖母,已是汗流浹背士鸥。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留谆级,地道東北人烤礁。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像肥照,于是被迫代替她去往敵國和親脚仔。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,066評論 2 355