Java IO流詳解(二)——IO流的框架體系

本篇文章主要介紹IO流的分類(lèi)、概念以及IO流中的四大基類(lèi),通過(guò)對(duì)IO流中的框架體系進(jìn)行介紹,對(duì)IO流有一個(gè)整體的了解。

一、IO流的概念

Java的IO流是實(shí)現(xiàn)輸入/輸出的基礎(chǔ),它可以方便地實(shí)現(xiàn)數(shù)據(jù)的輸入/輸出操作,在Java中把不同的輸入/輸出源抽象表述為"流"。流是一組有順序的,有起點(diǎn)和終點(diǎn)的字節(jié)集合,是對(duì)數(shù)據(jù)傳輸?shù)目偡Q(chēng)或抽象。即數(shù)據(jù)在兩設(shè)備間的傳輸稱(chēng)為流,流的本質(zhì)是數(shù)據(jù)傳輸,根據(jù)數(shù)據(jù)傳輸特性將流抽象為各種類(lèi),方便更直觀的進(jìn)行數(shù)據(jù)操作。
流有輸入和輸出,輸入時(shí)是流從數(shù)據(jù)源流向程序。輸出時(shí)是流從程序傳向數(shù)據(jù)源,而數(shù)據(jù)源可以是內(nèi)存,文件,網(wǎng)絡(luò)或程序等。

二、IO流的分類(lèi)

1.輸入流和輸出流

根據(jù)數(shù)據(jù)流向不同分為:輸入流和輸出流。

輸入流:只能從中讀取數(shù)據(jù),而不能向其寫(xiě)入數(shù)據(jù)。
輸出流:只能向其寫(xiě)入數(shù)據(jù),而不能從中讀取數(shù)據(jù)。

如下如所示:對(duì)程序而言,向右的箭頭,表示輸入,向左的箭頭,表示輸出。


2.字節(jié)流和字符流

字節(jié)流和字符流和用法幾乎完全一樣,區(qū)別在于字節(jié)流和字符流所操作的數(shù)據(jù)單元不同。
字符流的由來(lái): 因?yàn)閿?shù)據(jù)編碼的不同,而有了對(duì)字符進(jìn)行高效操作的流對(duì)象。本質(zhì)其實(shí)就是基于字節(jié)流讀取時(shí),去查了指定的碼表。字節(jié)流和字符流的區(qū)別:
(1)讀寫(xiě)單位不同:字節(jié)流以字節(jié)(8bit)為單位,字符流以字符為單位,根據(jù)碼表映射字符,一次可能讀多個(gè)字節(jié)。
(2)處理對(duì)象不同:字節(jié)流能處理所有類(lèi)型的數(shù)據(jù)(如圖片、avi等),而字符流只能處理字符類(lèi)型的數(shù)據(jù)。

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

3.節(jié)點(diǎn)流和處理流

按照流的角色來(lái)分,可以分為節(jié)點(diǎn)流和處理流。
可以從/向一個(gè)特定的IO設(shè)備(如磁盤(pán)、網(wǎng)絡(luò))讀/寫(xiě)數(shù)據(jù)的流,稱(chēng)為節(jié)點(diǎn)流,節(jié)點(diǎn)流也被成為低級(jí)流。
處理流是對(duì)一個(gè)已存在的流進(jìn)行連接或封裝,通過(guò)封裝后的流來(lái)實(shí)現(xiàn)數(shù)據(jù)讀/寫(xiě)功能,處理流也被稱(chēng)為高級(jí)流。

//節(jié)點(diǎn)流,直接傳入的參數(shù)是IO設(shè)備
FileInputStream fis = new FileInputStream("test.txt");
//處理流,直接傳入的參數(shù)是流對(duì)象
BufferedInputStream bis = new BufferedInputStream(fis);

當(dāng)使用處理流進(jìn)行輸入/輸出時(shí),程序并不會(huì)直接連接到實(shí)際的數(shù)據(jù)源,沒(méi)有和實(shí)際的輸入/輸出節(jié)點(diǎn)連接。使用處理流的一個(gè)明顯好處是,只要使用相同的處理流,程序就可以采用完全相同的輸入/輸出代碼來(lái)訪問(wèn)不同的數(shù)據(jù)源,隨著處理流所包裝節(jié)點(diǎn)流的變化,程序?qū)嶋H所訪問(wèn)的數(shù)據(jù)源也相應(yīng)地發(fā)生變化。
實(shí)際上,Java使用處理流來(lái)包裝節(jié)點(diǎn)流是一種典型的裝飾器設(shè)計(jì)模式,通過(guò)使用處理流來(lái)包裝不同的節(jié)點(diǎn)流,既可以消除不同節(jié)點(diǎn)流的實(shí)現(xiàn)差異,也可以提供更方便的方法來(lái)完成輸入/輸出功能。

三、IO流的四大基類(lèi)

根據(jù)流的流向以及操作的數(shù)據(jù)單元不同,將流分為了四種類(lèi)型,每種類(lèi)型對(duì)應(yīng)一種抽象基類(lèi)。這四種抽象基類(lèi)分別為:InputStream,Reader,OutputStream以及Writer。四種基類(lèi)下,對(duì)應(yīng)不同的實(shí)現(xiàn)類(lèi),具有不同的特性。在這些實(shí)現(xiàn)類(lèi)中,又可以分為節(jié)點(diǎn)流和處理流。下面就是整個(gè)由著四大基類(lèi)支撐下,整個(gè)IO流的框架圖。



InputStream,Reader,OutputStream以及Writer,這四大抽象基類(lèi),本身并不能創(chuàng)建實(shí)例來(lái)執(zhí)行輸入/輸出,但它們將成為所有輸入/輸出流的模版,所以它們的方法是所有輸入/輸出流都可以使用的方法。類(lèi)似于集合中的Collection接口。

1.InputStream

InputStream 是所有的輸入字節(jié)流的父類(lèi),它是一個(gè)抽象類(lèi),主要包含三個(gè)方法:

//讀取一個(gè)字節(jié)并以整數(shù)的形式返回(0~255),如果返回-1已到輸入流的末尾。 
int read() ; 
//讀取一系列字節(jié)并存儲(chǔ)到一個(gè)數(shù)組buffer,返回實(shí)際讀取的字節(jié)數(shù),如果讀取前已到輸入流的末尾返回-1。 
int read(byte[] buffer) ; 
//讀取length個(gè)字節(jié)并存儲(chǔ)到一個(gè)字節(jié)數(shù)組buffer,從off位置開(kāi)始存,最多l(xiāng)en, 返回實(shí)際讀取的字節(jié)數(shù),如果讀取前以到輸入流的末尾返回-1。 
int read(byte[] buffer, int off, int len) ; 

2.Reader

Reader 是所有的輸入字符流的父類(lèi),它是一個(gè)抽象類(lèi),主要包含三個(gè)方法:

//讀取一個(gè)字符并以整數(shù)的形式返回(0~255),如果返回-1已到輸入流的末尾。 
int read() ; 
//讀取一系列字符并存儲(chǔ)到一個(gè)數(shù)組buffer,返回實(shí)際讀取的字符數(shù),如果讀取前已到輸入流的末尾返回-1。 
int read(char[] cbuf) ; 
//讀取length個(gè)字符,并存儲(chǔ)到一個(gè)數(shù)組buffer,從off位置開(kāi)始存,最多讀取len,返回實(shí)際讀取的字符數(shù),如果讀取前以到輸入流的末尾返回-1。 
int read(char[] cbuf, int off, int len) 

對(duì)比InputStream和Reader所提供的方法,就不難發(fā)現(xiàn)兩個(gè)基類(lèi)的功能基本一樣的,只不過(guò)讀取的數(shù)據(jù)單元不同。

在執(zhí)行完流操作后,要調(diào)用close()方法來(lái)關(guān)系輸入流,因?yàn)槌绦蚶锎蜷_(kāi)的IO資源不屬于內(nèi)存資源,垃圾回收機(jī)制無(wú)法回收該資源,所以應(yīng)該顯式關(guān)閉文件IO資源。

除此之外,InputStream和Reader還支持如下方法來(lái)移動(dòng)流中的指針位置:

//在此輸入流中標(biāo)記當(dāng)前的位置
//readlimit - 在標(biāo)記位置失效前可以讀取字節(jié)的最大限制。
void mark(int readlimit)
// 測(cè)試此輸入流是否支持 mark 方法
boolean markSupported()
// 跳過(guò)和丟棄此輸入流中數(shù)據(jù)的 n 個(gè)字節(jié)/字符
long skip(long n)
//將此流重新定位到最后一次對(duì)此輸入流調(diào)用 mark 方法時(shí)的位置
void reset()

3.OutputStream

OutputStream 是所有的輸出字節(jié)流的父類(lèi),它是一個(gè)抽象類(lèi),主要包含如下四個(gè)方法:

//向輸出流中寫(xiě)入一個(gè)字節(jié)數(shù)據(jù),該字節(jié)數(shù)據(jù)為參數(shù)b的低8位。 
void write(int b) ; 
//將一個(gè)字節(jié)類(lèi)型的數(shù)組中的數(shù)據(jù)寫(xiě)入輸出流。 
void write(byte[] b); 
//將一個(gè)字節(jié)類(lèi)型的數(shù)組中的從指定位置(off)開(kāi)始的,len個(gè)字節(jié)寫(xiě)入到輸出流。 
void write(byte[] b, int off, int len); 
//將輸出流中緩沖的數(shù)據(jù)全部寫(xiě)出到目的地。 
void flush();

4.Writer

Writer 是所有的輸出字符流的父類(lèi),它是一個(gè)抽象類(lèi),主要包含如下六個(gè)方法:

//向輸出流中寫(xiě)入一個(gè)字符數(shù)據(jù),該字節(jié)數(shù)據(jù)為參數(shù)b的低16位。 
void write(int c); 
//將一個(gè)字符類(lèi)型的數(shù)組中的數(shù)據(jù)寫(xiě)入輸出流, 
void write(char[] cbuf) 
//將一個(gè)字符類(lèi)型的數(shù)組中的從指定位置(offset)開(kāi)始的,length個(gè)字符寫(xiě)入到輸出流。 
void write(char[] cbuf, int offset, int length); 
//將一個(gè)字符串中的字符寫(xiě)入到輸出流。 
void write(String string); 
//將一個(gè)字符串從offset開(kāi)始的length個(gè)字符寫(xiě)入到輸出流。 
void write(String string, int offset, int length); 
//將輸出流中緩沖的數(shù)據(jù)全部寫(xiě)出到目的地。 
void flush() 

可以看出,Writer比OutputStream多出兩個(gè)方法,主要是支持寫(xiě)入字符和字符串類(lèi)型的數(shù)據(jù)。

使用Java的IO流執(zhí)行輸出時(shí),不要忘記關(guān)閉輸出流,關(guān)閉輸出流除了可以保證流的物理資源被回收之外,還能將輸出流緩沖區(qū)的數(shù)據(jù)flush到物理節(jié)點(diǎn)里(因?yàn)樵趫?zhí)行close()方法之前,自動(dòng)執(zhí)行輸出流的flush()方法)

以上內(nèi)容就是整個(gè)IO流的框架介紹。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容