Java 之IO流總結(jié)筆記

流的概念

流是一種抽象概念,它代表了數(shù)據(jù)的無結(jié)構(gòu)化傳遞措近。按照流的方式進行輸入輸出,數(shù)據(jù)被當(dāng)成無結(jié)構(gòu)的字節(jié)序或字符序列女淑。從流中取得數(shù)據(jù)的操作稱為提取操作瞭郑,而向流中添加數(shù)據(jù)的操作稱為插入操作。用來進行輸入輸出操作的流就稱為IO流鸭你。換句話說屈张,IO流就是以流的方式進行輸入輸出擒权。

IO流的分類

  • 根據(jù)處理數(shù)據(jù)類型的不同分為:字符流和字節(jié)流
  • 根據(jù)數(shù)據(jù)流向不同分為:輸入流和輸出流

字符流和字節(jié)流

字符流的由來: 因為數(shù)據(jù)編碼的不同,而有了對字符進行高效操作的流對象阁谆。本質(zhì)其實就是基于字節(jié)流讀取時碳抄,去查了指定的碼表。 字節(jié)流和字符流的區(qū)別:

? 讀寫單位不同:字節(jié)流以字節(jié)(8bit)為單位场绿,字符流以字符為單位剖效,根據(jù)碼表映射字符,一次可能讀多個字節(jié)焰盗。
? 處理對象不同:字節(jié)流能處理所有類型的數(shù)據(jù)(如圖片璧尸、avi等),而字符流只能處理字符類型的數(shù)據(jù)

結(jié)論:只要是處理純文本數(shù)據(jù)熬拒,就優(yōu)先考慮使用字符流爷光。 除此之外都使用字節(jié)流。

輸入流和輸出流

對輸入流只能進行讀操作澎粟,對輸出流只能進行寫操作蛀序,程序中需要根據(jù)待傳輸數(shù)據(jù)的不同特性而使用不同的流。

IO流的家族關(guān)系圖:


IO流Java

Java IO流對象

1.輸入字節(jié)流InputStream

  • 1.1 InputStream 是所有的輸入字節(jié)流的父類活烙,它是一個抽象類徐裸。

  • 1.2 ByteArrayInputStream、StringBufferInputStream瓣颅、FileInputStream 是三種基本的介質(zhì)流倦逐,它們分別從Byte 數(shù)組、StringBuffer宫补、和本地文件中讀取數(shù)據(jù)檬姥。PipedInputStream 是從與其它線程共用的管道中讀取數(shù)據(jù),與Piped 相關(guān)的知識后續(xù)單獨介紹粉怕。

  • 1.3 ObjectInputStream 和所有FilterInputStream 的子類都是裝飾流
    (裝飾器模式的主角)健民。

2.輸出字節(jié)流OutputStream

    1. OutputStream 是所有的輸出字節(jié)流的父類,它是一個抽象類贫贝。
    1. ByteArrayOutputStream秉犹、FileOutputStream 是兩種基本的介質(zhì)流,它們分別向Byte 數(shù)組稚晚、和本地文件中寫入數(shù)據(jù)崇堵。PipedOutputStream 是向與其它線程共用的管道中寫入數(shù)據(jù)。
    1. ObjectOutputStream 和所有FilterOutputStream 的子類都是裝飾流客燕。

3.字節(jié)流的輸入與輸出的對應(yīng)

字節(jié)流對應(yīng)圖

圖中藍色的為主要的對應(yīng)部分鸳劳,紅色的部分就是不對應(yīng)部分。紫色的虛線部分代表這些流一般要搭配使用也搓。從上面的圖中可以看出Java IO 中的字節(jié)流是極其對稱的赏廓。

“存在及合理”我們看看這些字節(jié)流中不太對稱的幾個類:

    1. LineNumberInputStream 主要完成從流中讀取數(shù)據(jù)時涵紊,會得到相應(yīng)的行號,至于什么時候分行幔摸、在哪里分行是由改類主動確定的摸柄,并不是在原始中有這樣一個行號。在輸出部分沒有對應(yīng)的部分既忆,我們完全可以自己建立一個LineNumberOutputStream驱负,在最初寫入時會有一個基準(zhǔn)的行號,以后每次遇到換行時會在下一行添加一個行號尿贫,看起來也是可以的电媳。好像更不入流了。
    1. PushbackInputStream 的功能是查看最后一個字節(jié)庆亡,不滿意就放入緩沖區(qū)。主要用在編譯器的語法捞稿、詞法分析部分又谋。輸出部分的BufferedOutputStream 幾乎實現(xiàn)相近的功能。
    1. StringBufferInputStream 已經(jīng)被Deprecated娱局,本身就不應(yīng)該出現(xiàn)在InputStream 部分彰亥,主要因為String 應(yīng)該屬于字符流的范圍。已經(jīng)被廢棄了衰齐,當(dāng)然輸出部分也沒有必要需要它了任斋!還允許它存在只是為了保持版本的向下兼容而已。
    1. SequenceInputStream 可以認為是一個工具類耻涛,將兩個或者多個輸入流當(dāng)成一個輸入流依次讀取废酷。完全可以從IO 包中去除,還完全不影響IO 包的結(jié)構(gòu)抹缕,卻讓其更“純潔”――純潔的Decorator 模式澈蟆。
    1. PrintStream 也可以認為是一個輔助工具。主要可以向其他輸出流卓研,或者FileInputStream 寫入數(shù)據(jù)趴俘,本身內(nèi)部實現(xiàn)還是帶緩沖的。本質(zhì)上是對其它流的綜合運用的一個工具而已奏赘。一樣可以踢出IO 包寥闪!System.out 和System.out 就是PrintStream 的實例!

4.字符輸入流Reader

    1. Reader 是所有的輸入字符流的父類磨淌,它是一個抽象類疲憋。
    1. CharReader、StringReader 是兩種基本的介質(zhì)流伦糯,它們分別將Char 數(shù)組柜某、String中讀取數(shù)據(jù)嗽元。PipedReader 是從與其它線程共用的管道中讀取數(shù)據(jù)。
    1. BufferedReader 很明顯就是一個裝飾器喂击,它和其子類負責(zé)裝飾其它Reader 對象剂癌。
    1. FilterReader 是所有自定義具體裝飾流的父類,其子類PushbackReader 對Reader 對象進行裝飾翰绊,會增加一個行號佩谷。
    1. InputStreamReader 是一個連接字節(jié)流和字符流的橋梁,它將字節(jié)流轉(zhuǎn)變?yōu)樽址骷嗍取ileReader 可以說是一個達到此功能谐檀、常用的工具類,在其源代碼中明顯使用了將FileInputStream 轉(zhuǎn)變?yōu)镽eader 的方法裁奇。我們可以從這個類中得到一定的技巧桐猬。Reader 中各個類的用途和使用方法基本和InputStream 中的類使用一致。后面會有Reader 與InputStream 的對應(yīng)關(guān)系刽肠。

5.字符輸出流Writer

    1. Writer 是所有的輸出字符流的父類溃肪,它是一個抽象類。
    1. CharArrayWriter音五、StringWriter 是兩種基本的介質(zhì)流惫撰,它們分別向Char 數(shù)組、String 中寫入數(shù)據(jù)躺涝。PipedWriter 是向與其它線程共用的管道中寫入數(shù)據(jù)厨钻。
    1. BufferedWriter 是一個裝飾器為Writer 提供緩沖功能。
    1. PrintWriter 和PrintStream 極其類似坚嗜,功能和使用也非常相似夯膀。
    1. OutputStreamWriter 是OutputStream 到Writer 轉(zhuǎn)換的橋梁,它的子類FileWriter 其實就是一個實現(xiàn)此功能的具體類(具體可以研究一SourceCode)惶傻。功能和使用和OutputStream 極其類似棍郎,后面會有它們的對應(yīng)圖。

6.字符流的輸入與輸出的對應(yīng)

字符流的輸入與輸出的對應(yīng)

7.字符流與字節(jié)流轉(zhuǎn)換

轉(zhuǎn)換流的特點:

  1. 其是字符流和字節(jié)流之間的橋梁
  2. 可對讀取到的字節(jié)數(shù)據(jù)經(jīng)過指定編碼轉(zhuǎn)換成字符
  3. 可對讀取到的字符數(shù)據(jù)經(jīng)過指定編碼轉(zhuǎn)換成字節(jié)

何時使用轉(zhuǎn)換流银室?

    1. 當(dāng)字節(jié)和字符之間有轉(zhuǎn)換動作時涂佃;
    1. 流操作的數(shù)據(jù)需要編碼或解碼時。

具體的對象體現(xiàn):

    1. InputStreamReader:字節(jié)到字符的橋梁
    1. OutputStreamWriter:字符到字節(jié)的橋梁
      這兩個流對象是字符體系中的成員蜈敢,它們有轉(zhuǎn)換作用辜荠,本身又是字符流,所以在構(gòu)造的時候需要傳入字節(jié)流對象進來抓狭。

8.File類

File類是對文件系統(tǒng)中文件以及文件夾進行封裝的對象伯病,可以通過對象的思想來操作文件和文件夾。 File類保存文件或目錄的各種元數(shù)據(jù)信息,包括文件名午笛、文件長度惭蟋、最后修改時間、是否可讀药磺、獲取當(dāng)前文件的路徑名告组,判斷指定文件是否存在、獲得當(dāng)前目錄中的文件列表癌佩,創(chuàng)建木缝、刪除文件和目錄等方法。

9.RandomAccessFile類

該對象并不是流體系中的一員围辙,其封裝了字節(jié)流我碟,同時還封裝了一個緩沖區(qū)(字符數(shù)組),通過內(nèi)部的指針來操作字符數(shù)組中的數(shù)據(jù)姚建。 該對象特點:

  1. 該對象只能操作文件矫俺,所以構(gòu)造函數(shù)接收兩種類型的參數(shù):a.字符串文件路徑;b.File對象桥胞。
  2. 該對象既可以對文件進行讀操作恳守,也能進行寫操作,在進行對象實例化時可指定操作模式

下面來看一些具體的代碼例子:

按字節(jié)來讀取文件

public class ReadFromFile {
    /**
     * 以字節(jié)為單位讀取文件贩虾,常用于讀二進制文件,如圖片沥阱、聲音缎罢、影像等文件。
     */
    public static void readFileByBytes(String fileName) {
        File file = new File(fileName);
        InputStream in = null;
        try {
            System.out.println("以字節(jié)為單位讀取文件內(nèi)容考杉,一次讀一個字節(jié):");
            // 一次讀一個字節(jié)
            in = new FileInputStream(file);
            int tempbyte;
            while ((tempbyte = in.read()) != -1) {
                System.out.print(tempbyte);
            }
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }
        try {
            System.out.println("以字節(jié)為單位讀取文件內(nèi)容策精,一次讀多個字節(jié):");
            // 一次讀多個字節(jié)
            byte[] tempbytes = new byte[100];
            int byteread = 0;
            in = new FileInputStream(fileName);
            ReadFromFile.showAvailableBytes(in);
            // 讀入多個字節(jié)到字節(jié)數(shù)組中,byteread為一次讀入的字節(jié)數(shù)
            while ((byteread = in.read(tempbytes)) != -1) {
                System.out.print(tempbytes, 0, byteread);
            }
        } catch (Exception e1) {
            e1.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e1) {
                }
            }
        }
    }

按字符來讀取文件

/**
     * 以字符為單位讀取文件崇棠,常用于讀文本,數(shù)字等類型的文件
     */
    public static void readFileByChars(String fileName) {
        File file = new File(fileName);
        Reader reader = null;
        try {
            System.out.println("以字符為單位讀取文件內(nèi)容,一次讀一個字符:");
            // 一次讀一個字符
            reader = new InputStreamReader(new FileInputStream(file));
            int tempchar;
            while ((tempchar = reader.read()) != -1) {
                // 對于windows下弱恒,\r\n這兩個字符在一起時旦万,表示一個換行。
                // 但如果這兩個字符分開顯示時萎坷,會換兩次行凹联。
                // 因此,屏蔽掉\r哆档,或者屏蔽\n蔽挠。否則,將會多出很多空行瓜浸。
                if (((char) tempchar) != '\r') {
                    System.out.print((char) tempchar);
                }
            }
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            System.out.println("以字符為單位讀取文件內(nèi)容澳淑,一次讀多個字符:");
            // 一次讀多個字符
            char[] tempchars = new char[30];
            int charread = 0;
            //由于要以字符來讀取比原,所以需要套上字符流
            reader = new InputStreamReader(new FileInputStream(fileName));
            // 讀入多個字符到字符數(shù)組中,charread為一次讀取字符數(shù)
            while ((charread = reader.read(tempchars)) != -1) {
                // 同樣屏蔽掉\r不顯示
                if ((charread == tempchars.length)
                        && (tempchars[tempchars.length - 1] != '\r')) {
                    System.out.print(tempchars);
                } else {
                    for (int i = 0; i < charread; i++) {
                        if (tempchars[i] == '\r') {
                            continue;
                        } else {
                            System.out.print(tempchars[i]);
                        }
                    }
                }
            }

        } catch (Exception e1) {
            e1.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                }
            }
        }
    }

按行來讀取文件

/**
     * 以行為單位讀取文件杠巡,常用于讀面向行的格式化文件
     */
    public static void readFileByLines(String fileName) {
        File file = new File(fileName);
        BufferedReader reader = null;
        try {
            System.out.println("以行為單位讀取文件內(nèi)容量窘,一次讀一整行:");
            reader = new BufferedReader(new FileReader(file));
            String tempString = null;
            int line = 1;
            // 一次讀入一行,直到讀入null為文件結(jié)束
            while ((tempString = reader.readLine()) != null) {
                // 顯示行號
                System.out.println("line " + line + ": " + tempString);
                line++;
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                }
            }
        }
    }

將一個文件的內(nèi)容寫入另一個文件(按行來寫)

public class FileTest {
public static void main(String[] args)   {
 File  file=new File("c:\\test.txt");
 BufferedReader read=null;
 BufferedWriter writer=null;
 try {
   writer=new BufferedWriter(new  FileWriter("c:\\zwm.txt"));
 } catch (IOException e1) {
  e1.printStackTrace();
 }
 try {
   read=new BufferedReader(new  FileReader(file));
   String tempString = null;
   while((tempString=read.readLine())!=null){
    writer.append(tempString);
    writer.newLine();//換行
    writer.flush();//需要及時清掉流的緩沖區(qū)忽孽,萬一文件過大就有可能無法寫入了
   }
   read.close();
   writer.close();
   System.out.println("文件寫入完成...");
 } catch (IOException e) {
  e.printStackTrace();
 }

}
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末绑改,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子兄一,更是在濱河造成了極大的恐慌厘线,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件出革,死亡現(xiàn)場離奇詭異造壮,居然都是意外死亡,警方通過查閱死者的電腦和手機骂束,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進店門耳璧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人展箱,你說我怎么就攤上這事旨枯。” “怎么了混驰?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵攀隔,是天一觀的道長。 經(jīng)常有香客問我栖榨,道長昆汹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任婴栽,我火速辦了婚禮满粗,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘愚争。我一直安慰自己映皆,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布准脂。 她就那樣靜靜地躺著劫扒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪狸膏。 梳的紋絲不亂的頭發(fā)上沟饥,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天,我揣著相機與錄音,去河邊找鬼贤旷。 笑死广料,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的幼驶。 我是一名探鬼主播艾杏,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼盅藻!你這毒婦竟也來了购桑?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤氏淑,失蹤者是張志新(化名)和其女友劉穎勃蜘,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體假残,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡缭贡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了辉懒。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片阳惹。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖眶俩,靈堂內(nèi)的尸體忽然破棺而出莹汤,到底是詐尸還是另有隱情,我是刑警寧澤颠印,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布体啰,位于F島的核電站,受9級特大地震影響嗽仪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜柒莉,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一闻坚、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧兢孝,春花似錦窿凤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至窗轩,卻和暖如春夯秃,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工仓洼, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留介陶,地道東北人。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓色建,卻偏偏與公主長得像哺呜,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子箕戳,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,871評論 2 354

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

  • tags:io categories:總結(jié) date: 2017-03-28 22:49:50 不僅僅在JAVA領(lǐng)...
    行徑行閱讀 2,178評論 0 3
  • 概述: 1某残、IO流:即Input Output的縮寫。 2陵吸、特點:1)IO流用來處理設(shè)備間的數(shù)據(jù)傳輸玻墅。2)Java...
    玉圣閱讀 1,253評論 0 3
  • 在經(jīng)過一次沒有準(zhǔn)備的面試后,發(fā)現(xiàn)自己雖然寫了兩年的android代碼走越,基礎(chǔ)知識卻忘的差不多了椭豫。這是程序員的大忌,沒...
    猿來如癡閱讀 2,841評論 3 10
  • 我喜歡晴天旨指,天上掛著一個紅彤彤的太陽赏酥。云朵是那樣飄逸,陽光是那樣燦爛谆构,在這時裸扶,我已在外面開始踩影子。 我喜歡雨天搬素。...
    周子軒閱讀 266評論 0 0
  • 誰能告訴我,在百度上搜高長恭復(fù)原圖粱哼,為什么會出來這樣新聞和圖片:2014年10月9日 - 近日,蘭陵王高長恭電腦復(fù)...
    淼淼久愛閱讀 8,231評論 9 3