I/O輸入/輸出

引言

對(duì)程序語(yǔ)言設(shè)計(jì)者來(lái)說(shuō)野舶,設(shè)計(jì)一個(gè)令人滿(mǎn)意的I/O(輸入輸出)系統(tǒng)峦耘,是件極艱巨的任務(wù)砌们,摘自《Thinking in Java 》

概述

JAVA程序通過(guò)流來(lái)完成輸入/輸出贩虾。流是生產(chǎn)或消費(fèi)信息的抽象催烘,流通過(guò)Java的輸入/輸出系統(tǒng)與物理設(shè)備連接。JAVA的I/O通過(guò)java.io包下的類(lèi)和接口來(lái)支持缎罢,主要是5個(gè)類(lèi)和一個(gè)接口伊群。

  • File:用于文件或目錄的描述信息,例如生成新目錄策精,修改文件名舰始,刪除文件,判斷文件路徑等
  • InputStream:抽象類(lèi)咽袜,所有輸入流的父類(lèi)丸卷,定義了所有輸入流具有的共同特征。
  • OutputStream:抽象類(lèi)酬蹋,基于字節(jié)的輸出操作及老,所有輸出流的父類(lèi)抽莱,定義了輸出流具有的共同特征范抓。
  • Reader:抽象類(lèi),基于字符的輸入類(lèi)食铐。
  • Writer:抽象類(lèi)匕垫,基于字符的輸出類(lèi)。
  • Serializable:將Java對(duì)象轉(zhuǎn)換成平臺(tái)無(wú)關(guān)的二進(jìn)制數(shù)據(jù)
  • RandomAccessFile:包裝了一個(gè)隨機(jī)訪問(wèn)的文件虐呻,實(shí)現(xiàn)了DataInput/DataOutput接口象泵。
File類(lèi)

一個(gè)File類(lèi)的對(duì)象寞秃,表示了磁盤(pán)上的文件或目錄,提供了與平臺(tái)無(wú)關(guān)的方法來(lái)對(duì)磁盤(pán)上的文件或者目錄進(jìn)行操作偶惠,直接處理文件或目錄春寿,但是不能訪問(wèn)文件本身。

在java.io包中提供了60多了類(lèi)流:

從功能上分為:

  • 輸入流:從外部流向內(nèi)存
  • 輸出流:從內(nèi)存流向外部

從流的角色上分為:

  • 節(jié)點(diǎn)流:可以從/向一個(gè)特定的IO設(shè)備(磁盤(pán)忽孽,網(wǎng)絡(luò))讀/寫(xiě)數(shù)據(jù)的流绑改,直接連接物理設(shè)備或socket
  • 處理流:對(duì)一個(gè)已經(jīng)存在的流(節(jié)點(diǎn)流)進(jìn)行連接或者封裝。

從流的結(jié)構(gòu)上分為:

  • 字節(jié)流 :InputStream OutputStream
  • 字符流 : Reader Writer

在最底層兄一,所有的輸入輸出都是以字節(jié)為單位的厘线,基于字符的流只是為處理字符提供方便有效的方法。它們的操作方式幾乎完全一樣出革,只是操作的數(shù)據(jù)單元不同造壮,字節(jié)流操作的數(shù)據(jù)單元是字符,字符流操作的數(shù)據(jù)單元是字符骂束。

類(lèi)流全家福

I/O流類(lèi).png

從上面的圖片中耳璧,可以看出無(wú)論是字節(jié)流和字符流都提供了對(duì)文件,數(shù)組展箱,字符串楞抡,管道,對(duì)象析藕,音頻等內(nèi)容的輸入/輸出流支持召廷。

對(duì)輸入/輸出流基類(lèi)的簡(jiǎn)單介紹

InputSteam 三個(gè)基本的讀方法:
abstract int read(): 讀取一個(gè)字節(jié)數(shù)據(jù),并返回讀到數(shù)據(jù)的末尾账胧,如果返回-1 竞慢, 表示都到了輸入流的末尾。

int read(byte[] b ): 將數(shù)據(jù)讀入一個(gè)字節(jié)數(shù)組治泥,同時(shí)返回實(shí)際讀取的字節(jié)數(shù)筹煮,如果返回-1 ,表示讀到了輸入流的末尾居夹。

int read(byte[] b , int off , int len):將數(shù)據(jù)讀入一個(gè)字節(jié)數(shù)組败潦,同時(shí)返回實(shí)際讀取的字節(jié)數(shù),如果返回-1 准脂,表示讀到了輸入流的末尾劫扒,off指定在數(shù)組b中存放數(shù)據(jù)的起始位置,len指定讀取的最大字節(jié)數(shù)狸膏。

可能會(huì)有一個(gè)疑問(wèn)沟饥,為什么上面的第一個(gè)方法是抽象,而其余兩個(gè)read方法是具體的? 通過(guò)源碼找到了想要的答案。第二個(gè)方法依靠了第三個(gè)方法贤旷,而第三個(gè)方法依靠了第一個(gè)方法實(shí)現(xiàn)广料,換句話說(shuō)只有第一個(gè)read方法是與具體的I/O設(shè)備相關(guān)的,需要InputStream的子類(lèi)來(lái)實(shí)現(xiàn)幼驶。源碼如下:

public abstract int read() throws IOException;

public int read(byte b[]) throws IOException {
        return read(b, 0, b.length);  //調(diào)用第三個(gè)方法實(shí)現(xiàn)
    }

public int read(byte b[], int off, int len) throws IOException {
        //判斷參數(shù)的合法性
        if (b == null) {
            throw new NullPointerException();
        } else if (off < 0 || len < 0 || len > b.length - off) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return 0;
        }
        
        int c = read();   //調(diào)用第一個(gè)方法艾杏,讀取一個(gè)字節(jié)
        if (c == -1) {
            return -1;   //沒(méi)有字節(jié)返回-1 ,讀取結(jié)束
        }
        b[off] = (byte)c;  //將讀取到的字節(jié)放入數(shù)組中

        int i = 1;
        try {
            for (; i < len ; i++) {
                c = read();
                if (c == -1) {
                    break;
                }
                b[off + i] = (byte)c;  //將讀取到的字節(jié)放入數(shù)組中盅藻,讀取的長(zhǎng)度大于數(shù)據(jù)長(zhǎng)度糜颠,循環(huán)讀取結(jié)束
            }
        } catch (IOException ee) {
        }
        return i;  //返回讀取的字節(jié)數(shù)組長(zhǎng)度
    }

其它方法
long skip(long n ):輸入流中跳過(guò)n個(gè)字節(jié),并返回實(shí)際跳過(guò)的字節(jié)數(shù)
void close():關(guān)閉流
萧求。其兴。。

OutputStream 主要方法
void write(byte[]] b ):將參數(shù)b中的字節(jié)寫(xiě)到輸出流
void write(byte[] b , int off ,int len):將參數(shù)b的從偏移量off開(kāi)始len個(gè)字節(jié)寫(xiě)到輸出流
abstract viud write(int b ):先將int轉(zhuǎn)換成byte類(lèi)型夸政,把低字節(jié)寫(xiě)入到輸出流中
void flush():將緩沖區(qū)中的字節(jié)全部輸出元旬,并清空緩存區(qū)
void close():關(guān)閉輸出流并釋放與流相關(guān)的系統(tǒng)資源

Reader里包含的3個(gè)讀取方法:
int read():
int read(char[] c):
int read(char[] c ,int off , int len) :

Write包含的方法
void write(char[] c)
void write(String str)
void write(String str, int off, int len)
abstract flush()
void close()

根據(jù)上面圖片做一個(gè)簡(jiǎn)單的總結(jié):

  • FileInputStream和FileOutputStream 節(jié)點(diǎn)流,用于對(duì)文件讀取或往文件中寫(xiě)入字節(jié)流守问。如果在構(gòu)造FileOutputStream時(shí)匀归,文件已經(jīng)存在,則覆蓋整個(gè)文件耗帕。
  • BufferedInputStream和BufferedOutputStream過(guò)濾流穆端,需要使用已經(jīng)存在的節(jié)點(diǎn)流來(lái)構(gòu)造,提供了讀寫(xiě)的效率仿便。
  • DataInputStream和DataOutputStream 過(guò)濾流体啰,需要使用已經(jīng)存在的節(jié)點(diǎn)流來(lái)構(gòu)造,提供了讀寫(xiě)Java中基本數(shù)據(jù)類(lèi)型的功能嗽仪。
  • PipedInputStream和PipedOutputStream 管道流荒勇,用于線程間的通信,一個(gè)線程的PipedInputStream對(duì)象從另一個(gè)線程的PipedOutputStream 對(duì)象讀取輸入闻坚,只要管道流有用沽翔,必須提供同時(shí)構(gòu)造管道輸入流和管道輸出流。
  • InputStreamReader和OutputStreamWriter類(lèi)窿凤,用于處理字符流的基本類(lèi)仅偎,用來(lái)在字節(jié)流和字符流之間搭一座橋。將字節(jié)流和字符流進(jìn)行轉(zhuǎn)換雳殊。
  • FileReader和FileWriter 可以創(chuàng)建一個(gè)可以讀/寫(xiě)文件的類(lèi)橘沥。
  • BufferedReader:通過(guò)緩沖輸入提高性能。
  • SequenceInputStream:把多個(gè)InputStream合并為一個(gè)InputStream

I/O流的鏈接示意圖:

流的鏈接示意圖.png

常用類(lèi)
FileInputStream , FileOutputStream , ByteArrayInputStream, ByteArrayOutputStream 相种,BufferedReader,BufferedWriter, ,InputStreamReader ,InputStreamWriter威恼,F(xiàn)ileReader ,FileWriter

如何選擇I/O流

確定是輸入還是輸出

輸入:輸入流 InputStream Reader
輸出:輸出流 OutputStream Writer

明確操作的數(shù)據(jù)對(duì)象是否是純文本

是:字符流 Reader,Writer
否:字節(jié)流 InputStream寝并,OutputStream

明確具體的設(shè)備箫措。

文件:
讀:FileInputStream,, FileReader,
寫(xiě):FileOutputStream,F(xiàn)ileWriter

數(shù)組:
byte[ ]:ByteArrayInputStream, ByteArrayOutputStream
char[ ]:CharArrayReader, CharArrayWriter

String:
StringBufferInputStream(已過(guò)時(shí)衬潦,因?yàn)槠渲荒苡糜赟tring的每個(gè)字符都是8位的字符串), StringReader, StringWriter

Socket流
鍵盤(pán):用System.in(是一個(gè)InputStream對(duì)象)讀取斤蔓,用System.out(是一個(gè)OutoutStream對(duì)象)打印

是否需要轉(zhuǎn)換流

是,就使用轉(zhuǎn)換流镀岛,從Stream轉(zhuǎn)化為Reader弦牡、Writer:InputStreamReader,OutputStreamWriter

是否需要緩沖提高效率

是就加上Buffered:BufferedInputStream, BufferedOuputStream, BufferedReader, BufferedWrite


少年聽(tīng)雨歌樓上漂羊,紅燭昏羅帳驾锰。  
壯年聽(tīng)雨客舟中,江闊云低走越,斷雁叫西風(fēng)椭豫。
感謝支持!
                                        ---起個(gè)名忒難

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末旨指,一起剝皮案震驚了整個(gè)濱河市赏酥,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌谆构,老刑警劉巖裸扶,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異搬素,居然都是意外死亡呵晨,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)熬尺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)何荚,“玉大人,你說(shuō)我怎么就攤上這事猪杭〔吞粒” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵皂吮,是天一觀的道長(zhǎng)戒傻。 經(jīng)常有香客問(wèn)我,道長(zhǎng)蜂筹,這世上最難降的妖魔是什么需纳? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮艺挪,結(jié)果婚禮上不翩,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好口蝠,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布器钟。 她就那樣靜靜地躺著,像睡著了一般妙蔗。 火紅的嫁衣襯著肌膚如雪傲霸。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,046評(píng)論 1 285
  • 那天眉反,我揣著相機(jī)與錄音昙啄,去河邊找鬼。 笑死寸五,一個(gè)胖子當(dāng)著我的面吹牛梳凛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播梳杏,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼伶跷,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了秘狞?” 一聲冷哼從身側(cè)響起叭莫,我...
    開(kāi)封第一講書(shū)人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎烁试,沒(méi)想到半個(gè)月后雇初,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡减响,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年靖诗,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片支示。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡刊橘,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出颂鸿,到底是詐尸還是另有隱情促绵,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布嘴纺,位于F島的核電站败晴,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏栽渴。R本人自食惡果不足惜尖坤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望闲擦。 院中可真熱鬧慢味,春花似錦场梆、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至感昼,卻和暖如春装哆,著一層夾襖步出監(jiān)牢的瞬間罐脊,已是汗流浹背定嗓。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留萍桌,地道東北人宵溅。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像上炎,于是被迫代替她去往敵國(guó)和親恃逻。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

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

  • 一藕施、流的概念和作用寇损。 流是一種有順序的,有起點(diǎn)和終點(diǎn)的字節(jié)集合裳食,是對(duì)數(shù)據(jù)傳輸?shù)目偝苫虺橄竺小<磾?shù)據(jù)在兩設(shè)備之間的傳輸...
    布魯斯不吐絲閱讀 10,018評(píng)論 2 95
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類(lèi)相關(guān)的語(yǔ)法诲祸,內(nèi)部類(lèi)的語(yǔ)法浊吏,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法救氯,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,581評(píng)論 18 399
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理找田,服務(wù)發(fā)現(xiàn),斷路器着憨,智...
    卡卡羅2017閱讀 134,599評(píng)論 18 139
  • 朋友說(shuō)甲抖,戀愛(ài)的捷徑底桂,是有一個(gè)好的備胎。惡補(bǔ)了好多瑪麗蘇劇情才發(fā)現(xiàn)惧眠,只有綠茶婊才能輕松應(yīng)對(duì)八九十來(lái)個(gè)備胎籽懦,顯然,我不...
    木子魚(yú)兒閱讀 412評(píng)論 1 0
  • 周日上午在家氛魁,孩子說(shuō)作業(yè)寫(xiě)完了暮顺,想看手機(jī)視頻半小時(shí)厅篓,因?yàn)樽蛱炷苷f(shuō)到做到,就把手機(jī)給了他捶码。結(jié)果是看了一個(gè)小時(shí)才把手機(jī)...
    聽(tīng)雨聆聲閱讀 228評(píng)論 0 7