[筆記]Java IO之InputStream和OutputStream

InputStream和OutStream是java.io包中面向字節(jié)操作的兩個頂層抽象類,所有關(guān)于java同步IO字節(jié)流的操作都是基于這兩個的。

什么是流?

《O'Reilly-Java Io》中是這么解釋的:

A stream is an ordered sequence of bytes of undetermined length. Input streams move bytes
of data into a Java program from some generally external source. Output streams move bytes
of data from Java to some generally external target. (In special cases streams can also move
bytes from one part of a Java program to another.)

流是一個不確定長度的有序字節(jié)序列。輸入流從外部資源將數(shù)據(jù)字節(jié)移動到Java程序中。輸出流從Java程序中將數(shù)據(jù)字節(jié)移動到外部目標(biāo)。(特殊的情況也可以將字節(jié)從java程序中一部分移動到另一部分)

流從哪里來?

通常流來自于:
1、網(wǎng)絡(luò)
2、文件
3、java內(nèi)部程序

InputStream(輸入流):

InputStream作為java中用于讀取流中字節(jié)的頂層抽象類,定義了一些方法:

public abstract int read() throws IOException
public int read(byte b[], int off, int len) throws IOException
public int read(byte b[]) throws IOException {
        return read(b, 0, b.length);
}

有三個read方法用來讀取字節(jié):
1、第一個抽象方法交由子類來實現(xiàn),讀取一個無符號字節(jié),由于java本身沒有無符號字節(jié)的基本類型,所以用int作為返回值。當(dāng)返回-1時表示到了流的結(jié)尾,這也是需要返回int的原因之一(因為帶符號的byte有可能是-1)

2、
作用: 從流中讀取字節(jié)數(shù)組,通常一個一個字節(jié)的讀效率相當(dāng)?shù)拖拢芍付〝?shù)組中開始的偏移位置off,長度len
參數(shù): 保存字節(jié)的字節(jié)數(shù)組、偏移量、長度。
返回值: 實際讀到的字節(jié)數(shù)(-1為末尾)
默認(rèn)的實現(xiàn)依賴于第一個抽象方法,就是循環(huán)調(diào)用讀取一個無符號字節(jié)。所以效率不是很高,通常會有的子類以更高效的方式來重寫。

3、
作用: 從流中讀取字節(jié)數(shù)組,通常一個一個字節(jié)的讀效率相當(dāng)?shù)拖隆?br> 參數(shù): 保存字節(jié)的字節(jié)數(shù)組
返回值: 實際讀到的字節(jié)數(shù)(-1為末尾)
默認(rèn)的實現(xiàn)依賴于第二個方法,僅僅是用read(b,0,b.length)來實現(xiàn),重寫這個方法的子類相對較少。

public int available() throws IOException

作用: 從流中立刻能夠獲取到的字節(jié)數(shù)。
返回值: 能夠讀取到的字節(jié)數(shù)(沒有會返回0,到流的末尾也會返回0)

public long skip(long bytesToSkip) throws IOException

作用: 從流中跳過一定字節(jié)不讀,通常跳過比讀取后不處理快(比如文件流,只是指針的移動)。
參數(shù): 期望跳過的字節(jié)數(shù)
返回值:實際跳過的字節(jié)數(shù)(遇到末尾返回-1)

public void close() throws IOException

作用: 用完流之后,關(guān)閉流,但并不是所有的流都需要關(guān)閉,比如說System.in

關(guān)閉流的最佳實踐:
1、在finally中關(guān)閉

.
    InputStream in = null;
    try {
        in = new ...;
        ...
    } catch(IOException e) {
        ...
    } finally {
        try {
            if (in != null) {
                in.close();
            }
        } catch(IOException e) {
    
        }
    }

2、java7支持try-with-resources方式關(guān)閉流,實現(xiàn)了java.lang.AutoCloseable接口的對象支持用這種方式

.
    try (InputStream in = new ....){
        ...
    } catch(IOException e) {
        ...
    }

標(biāo)記和重置:

public synchronized void mark(int readLimit)
public synchronized void reset() throws IOException
public boolean markSupported()

有時候你讀取一些字節(jié)后希望返回到之前的位置重新讀,這幾個方法就是用來做這件事。

public boolean markSupported()

作用: 判斷當(dāng)前流是否支持標(biāo)記
返回值: 當(dāng)前流是否支持標(biāo)記
如果當(dāng)前流不支持標(biāo)記,執(zhí)行reset()方法將拋出一個IOException異常,而mark()方法不會做任何操作

public synchronized void mark(int readLimit)

作用: 將讀取的位置標(biāo)記在當(dāng)前位置。
參數(shù): 最大可閱讀超過標(biāo)記位置的字節(jié)數(shù)(只要沒有閱讀超過readLimit字節(jié)數(shù),就可以重置回去)
在同一時刻,只能有一個標(biāo)記,再設(shè)置會覆蓋
java.io中只有BufferedInputStreamByteArrayInputStream支持標(biāo)記。但是其他的過濾流連接到這兩個上也支持標(biāo)記。

OutputStream(輸出流):

OutputStream作為java中用于向流中寫字節(jié)的頂層抽象類,定義了一些方法:

public abstract void write(int b) throws IOException
public void write(byte[] data, int offset, int length) throws IOException
public void write(byte[] data) throws IOException

有三個write方法用來向流中寫字節(jié):

1、第一個是抽象方法交由子類實現(xiàn),向流中寫入一個無符號字節(jié)(0-255),如果超過255只會取低八位的字節(jié)。

2、作用: 向流中寫入字節(jié)數(shù)組,可以指定數(shù)組中起始的偏移位置和長度。
參數(shù): 寫入的字符數(shù)組、起始的偏移位置、長度
默認(rèn)的實現(xiàn)是循環(huán)調(diào)用第一個方法一個一個寫入,但是效率極其低下,子類一般會有更高效的方式

3、作用: 向流中寫入字節(jié)數(shù)組
參數(shù): 寫入的字符數(shù)組
默認(rèn)的實現(xiàn)是調(diào)用第二個write()方法write(b, 0, b.length);

public void flush() throws IOException

作用: 許多輸出流增加一個緩沖區(qū)來提升性能,當(dāng)緩沖區(qū)寫滿之后才會發(fā)送數(shù)據(jù),而flush()方法可以強(qiáng)制清空緩沖區(qū)發(fā)送數(shù)據(jù),如果不刷新則有可能導(dǎo)致數(shù)據(jù)丟失。通常PrintStreamprintln()方法會自動flush()

public void close() throws IOException

作用: 當(dāng)用完輸出流之后,將流關(guān)閉,關(guān)閉的同時也會flush()

無處不在的IOException:

IOException是受檢異常,在程序中必須被聲明。
IOException存在的意義是因為操作系統(tǒng)中的‘輸入’和‘輸出’是不可靠的,操作系統(tǒng)層級發(fā)生的異常是不受程序控制。

子類

java.io包中常用的子類:

其它包中還有一些類。

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

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

  • tags:io categories:總結(jié) date: 2017-03-28 22:49:50 不僅僅在JAVA領(lǐng)...
    行徑行閱讀 2,301評論 0 3
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,697評論 18 399
  • 在經(jīng)過一次沒有準(zhǔn)備的面試后,發(fā)現(xiàn)自己雖然寫了兩年的android代碼,基礎(chǔ)知識卻忘的差不多了。這是程序員的大忌,沒...
    猿來如癡閱讀 3,117評論 3 10
  • 《秋的姿態(tài)》 秋日清晨,乳白的輕霧像輕紗一樣籠罩在田野上,晨風(fēng)吹來,那紗輕輕舞動,霞光把輕霧染的坨紅,苗兒也變得晶...
    秋秋的深閱讀 259評論 6 11
  • 坐 靜坐 處子般嫻雅 掠過無聲 悄然綻放 行 行走 任性無壓力的釋放 可舉杯攬月 又可嬉戲耍鬧 …… 此一生 肩負(fù)...
    格小主閱讀 397評論 0 0

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