java.io 字節(jié)流

java.io 字節(jié)流

基類 InputStream 和 OutputStream

字節(jié)流主要操作 byte 類型數(shù)據(jù),以 byte 數(shù)組為準(zhǔn),java 中每一種字節(jié)流的基本功能依賴于基本類 InputStream 和 Outputstream,他們是抽象類,不能直接使用。字節(jié)流能處理所有類型的數(shù)據(jù)(如圖片、avi 等)。

InputStream

InputStream 是所有表示字節(jié)輸入流的基類,繼承它的子類要重新定義其中所有定義的抽象方法.InputStream是從裝置來源地讀取數(shù)據(jù)的抽象表示,例如System中的標(biāo)準(zhǔn)輸入流in對象就是一個InputStream類型的實例。

我們先來看看InputStream類的方法:

方法 說明
read()throws IOException 從輸入流中讀取數(shù)據(jù)的下一個字節(jié)(抽象方法)
skip(long n) throws IOException 跳過和丟棄此輸入流中數(shù)據(jù)的n個字節(jié)
available() throws IOException 返回流中可用字節(jié)數(shù)
mark(int readlimit) throws IOException 在此輸入流中標(biāo)記當(dāng)前的位置
reset() throws IOException 將此流重新定位到最后一次對此輸入流調(diào)用mark方法時的位置
markSupport() throws IOException 測試此輸入流是否支持mark 和 reset 方法
close() throws IOException 關(guān)閉流

在InputStream類中,方法read()提供了三種從流中讀數(shù)據(jù)的方法;

  1. int read(): 從輸入流中讀一個字節(jié),形成一個0~255之間的整數(shù)返回(是一個抽象方法)
  2. int read(byte b[]): 從輸入流中讀取一定數(shù)量的字節(jié),并將其存儲在緩沖區(qū)數(shù)組b中。
  3. int read(byte b[], int off,int len): 從輸入流中讀取長度為len的數(shù)據(jù),寫入數(shù)組b中從索引off開始的位置,并返回讀取的字節(jié)數(shù)。

對于這三個方法,若返回-1,表明流結(jié)束,否則,返回實際讀取的字符數(shù)。

OutputStream

OutputStream 是所有表示字節(jié)輸出流類的基類。子類要重新定義其中所定義的抽象方法,OutputStream 是用于將數(shù)據(jù)寫入目的地的抽象表示。例如 System 中的標(biāo)準(zhǔn)輸出流對象 out 其類型是 java.io.PrintStream,這個類是 OutputStream 的子類。

OutputStream 類方法:

方法 說明
write(int b)throws IOException 將指定的字節(jié)寫入此輸出流(抽象方法)
write(byte b[])throws IOException 將字節(jié)數(shù)組中的數(shù)據(jù)輸出到流中
write(byte b[], int off, int len)throws IOException 將指定 byte 數(shù)組中從偏移量 off 開始的 len 個字節(jié)寫入此輸出流
flush()throws IOException 刷新此輸出流并強制寫出所有緩沖的輸出字節(jié)
close()throws IOException 關(guān)閉流

看個例子

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class test {

    /**
     * 把輸入流中的所有內(nèi)容賦值到輸出流中
     * @param in
     * @param out
     * @throws IOException
     */
    public void copy(InputStream in, OutputStream out) throws IOException {
        byte[] buf = new  byte[4096];
        int len = in.read(buf);
        //read 是一個字節(jié)一個字節(jié)地讀,字節(jié)流的結(jié)尾標(biāo)志是-1
        while (len != -1){
            out.write(buf, 0, len);
            len = in.read(buf);
        }
    }
    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
        test t = new test();
        System.out.println("輸入字符:");
        t.copy(System.in, System.out);
    }

}

文件流

在 I/O 處理中,最常見的就是對文件的操作。java.io 包中所提供的文件操作類包括

  1. 用于讀寫本地文件系統(tǒng)中的文件:FileInputStream 和 FileOutputStream
  2. 描述本地文件系統(tǒng)中的文件或目錄: File、FileDescriptor 和 FilenameFilter
  3. 提供對本地文件系統(tǒng)中文件的隨機訪問支持:RandomAccessFile

今天我們來學(xué)習(xí)文件流的FileInputStream 和 FileOutputStream

FileInputStream 類用于打開一個輸入文件,若要打開的文件不存在,則會創(chuàng)建一個新的文件,否則原文件的內(nèi)容會被新寫入的內(nèi)容所覆蓋;

在進(jìn)行文件的讀/寫操作時,會產(chǎn)生非運行時異常IOException,必須捕獲或聲明拋棄(其他的輸入/輸出流處理時也同樣需要進(jìn)行輸入/輸出異常處理)

文件構(gòu)造方法:

//打開一個以 f 描述的文件作為輸入
FileInputStream(File f)

//打開一個文件路徑名為 name 的文件作為輸入
FileInputStream(String name)

//創(chuàng)建一個以 f 描述的文件作為輸出
//如果文件存在,則其內(nèi)容被清空
FileOutputStream(File f)

//創(chuàng)建一個文件路徑名為 name 的文件作為輸出
//文件如果已經(jīng)存在,則其內(nèi)容被清空
FileOutputStream(String name)

//創(chuàng)建一個文件路徑名為 name 的文件作為輸出
//文件如果已經(jīng)存在,則在該輸出上輸出的內(nèi)容被接到原有內(nèi)容之后
FileOutputStream(String name, boolean append)

示例代碼 :

File f1 = new File("file1.txt");
File f2 = new File("file2.txt");
FileInputStream in = new FileInputStream(f1);
FileOutputStream out = new FileOutputStream(f2);

輸入流的參數(shù)是用于指定輸入的文件名,輸出流的參數(shù)則是用于指定輸出的文件名

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

public class test {

    public static void main(String[] args) {
        try {
            //inFile 作為輸入流的數(shù)據(jù)文件必須存在,否則拋出異常
            File inFile = new File("/Users/mumutongxue/Documents/file1.txt");

            //file2.txt 沒有,系統(tǒng)可以創(chuàng)建,在 workspace 的 Test 項目下可以找到
            File outFile = new File("file2.txt");
            FileInputStream fis = new FileInputStream(inFile);
            FileOutputStream fos = new FileOutputStream(outFile);
            int c;
            while((c = fis.read()) != -1){
                fos.write(c);
            }
            //打開了文件一定要記著關(guān),釋放系統(tǒng)資源
            fis.close();
            fos.close();
        }catch(FileNotFoundException e) {
            System.out.println("FileStreamsTest:" + e);
        }catch(IOException e){
            System.err.println("FileStreamTest:" + e);
        }
    }

}

緩沖流

類BufferedInputStream 和 BufferedOutoutStream 實現(xiàn)了帶緩沖的過濾流,它提供了緩沖機制,把任意的I/O流“捆綁”到緩沖流上,可以提高I/O流的讀取效率

在初始化時,除了要指定所連接的I/O流之外,還可以指定緩沖區(qū)的大小,缺省時是用32字節(jié)大小的緩沖區(qū);最優(yōu)的緩沖區(qū)大小以來于主機操作系統(tǒng)、可使用的內(nèi)存空間以及機器的配置等;一般緩沖區(qū)的大小為內(nèi)存頁或磁盤塊等的整數(shù)倍

BufferedInputStream 的數(shù)據(jù)成員buf是一個位數(shù)組,默認(rèn)為2048字節(jié),當(dāng)讀取數(shù)據(jù)來源時例如文件,BufferedInputStream 會盡量將buf填滿。當(dāng)使用read() 方法時,實際上是先讀取buf中的數(shù)據(jù),而不是直接對數(shù)據(jù)來源作讀取。當(dāng)buf中的數(shù)據(jù)不足時,BufferedInputStream 才會再實現(xiàn)給定的InputStream對象的read() 方法,從指定的裝置中提取數(shù)據(jù)。

BufferedInputStream 的數(shù)據(jù)成員 buf 是一位數(shù)組,默認(rèn)為512字節(jié)。當(dāng)使用write() 方法寫入數(shù)據(jù)時,實際上會先將數(shù)據(jù)寫至buf中,當(dāng)buf已滿時才會實現(xiàn)給定的OutputStream 對象的write() 方法,將buf數(shù)據(jù)寫至目的地,而不是每次都對目的地作寫入的動作。

構(gòu)造方法:


//[ ] 里的內(nèi)容代表選填
BufferedInputStream(InputStream in [, int size])
BufferedOutputStream(OutputStream out [, int size])

舉個例子,將緩沖流與文件流相接

FileInputStream in = new FileInputStream("file.txt");
FileOutputStream out = new FileOutputStream("file2.txt");
//設(shè)置輸入緩沖區(qū)大小為 256 字節(jié)
BufferedInputStream bin = new BufferedInputStream(in,256)
BufferedOutputStream bout = new BufferedOutputStream(out,256)
int len;
byte bArray[] = new byte[256];
len = bin.read(bArray); //len 中得到的是實際讀取的長度,bArray 中得到的是數(shù)據(jù)

https://doc.shiyanlou.com/document-uid79144labid1113timestamp1436118879920.png/wm

對于 BufferedOutputStream,只有緩沖區(qū)滿時,才會將數(shù)據(jù)真正送到輸出流,但可以使用 flush() 方法人為地將尚未填滿的緩沖區(qū)中的數(shù)據(jù)送出。

例如方法copy();

public void copy(InputStream in, OutputStream out) throws IOException {
    out = new BufferedOutputStream(out, 4096);
    byte[] buf = new byte[4096];
    int len = in.read(buf);
    while (len != -1) {
    out.write(buf, 0, len);
    len = in.read(buf);
    }
    //最后一次讀取得數(shù)據(jù)可能不到 4096 字節(jié)
    out.flush();
}

數(shù)據(jù)流

接口 DataInput 和 DataOutput,設(shè)計了一種較為高級的數(shù)據(jù)輸入輸出方式:除了可處理字節(jié)和字節(jié)數(shù)組外,還可以處理 int、float、boolean 等基本數(shù)據(jù)類型,這些數(shù)據(jù)在文件中的表示方式和它們在內(nèi)存中的一樣,無須轉(zhuǎn)換,如 read(), readInt(), readByte()...; write(), writeChar(), writeBoolean()... 此外,還可以用 readLine() 方法讀取一行信息。

方法 :

方法 返回值 說明
readBoolean() boolean
readByte() byte
readShort() short
readChar() char
readInt() int
readLong() long
readDouble() double
readFloat() float
readUnsignedByte() int
readUnsignedShort() int
readFunlly(byte[] b) void 從輸入流中讀取一些字節(jié),并將它們存儲在緩沖區(qū)數(shù)組b中
reaFully(byte[] b, int off, int len) void 從輸入流中讀取len個字節(jié)
skipBytes(int n) int 與InputStream.skip 等價
readUTF() String 按照UTF-8形式從輸入中讀取字符串
readLine() String 按回車(\r)換行(\n)為分隔符讀取一行字符串,不完全支持UNICODE
writeBoolean(boolean v) void
writeByte(int v) void
writeShort(int v) void
writeChar(int v) void
writeInt(int v) void
writeLong(long v) void
writeFloat(float v) void
writeDouble(double v) void
write(byte[] b) void 與OutputStream.write 同義
write(byte[] b,int off,int len) void 與OutputStream.write 同義
write(int b) void 與OutputStream.write 同義
writeBytes(String s) void 只輸出每個字符的低 8 位;不完全支持 UNICODE
writeChars(String s) void 每個字符在輸出中都占兩個字節(jié)

數(shù)據(jù)流類 DataInputStream 和 DataOutputStream 的處理對象除了是字節(jié)或字節(jié)數(shù)組外,還可以實現(xiàn)對文件的不同數(shù)據(jù)類型的讀寫;

  1. 分別實現(xiàn)了DataInput 和 DataOutput 接口
  2. 在提供字節(jié)流的讀寫手段同時,以統(tǒng)一的形式向輸入流中寫入boolean,int,long,double 等基本數(shù)據(jù)類型,并可以再次把基本數(shù)據(jù)類型的值取回來
  3. 提供了字符串讀寫的手段

數(shù)據(jù)流可以連接一個已經(jīng)建立好的數(shù)據(jù)對象,例如網(wǎng)絡(luò)連接、文件等。數(shù)據(jù)流可以通過如下方式建立;

FileInputStream fis = new FileInputStream("file1.txt");
FileOutputStream fos = new FileOutputStream("file2.txt");
DataInputStream dis = new DataInputStream(fis);
DataOutputStream dos = new DataOutputStream(fos);

接下來我們通過具體的代碼,看一看它的用法吧;

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

public class DataStream {

    public static void main(String[] args) throws IOException{
        // TODO Auto-generated method stub
        //向文件 a.txt 寫入
        FileOutputStream fos = new FileOutputStream("a.txt");
        DataOutputStream dos = new DataOutputStream(fos);
        try {
            dos.writeBoolean(true);
            dos.writeByte((byte)123);
            dos.writeChar('J');
            dos.writeDouble(3.1415926);
            dos.writeFloat(2.122f);
            dos.writeInt(123);
        }
        finally {
            dos.close();
        }
        //從文件 a.txt 讀出
        FileInputStream fis = new FileInputStream("a.txt");
        DataInputStream dis = new DataInputStream(fis);
        try {
            System.out.println("\t" + dis.readBoolean());
            System.out.println("\t" + dis.readByte());
            System.out.println("\t" + dis.readChar());
            System.out.println("\t" + dis.readDouble());
            System.out.println("\t" + dis.readFloat());
            System.out.println("\t" + dis.readInt());
        }
        finally {
            dis.close();
        }
    }

}

標(biāo)準(zhǔn)流、內(nèi)存讀寫流、順序輸入流

標(biāo)準(zhǔn)流

語言包 java.lang 中的System類管理標(biāo)準(zhǔn)輸入/輸出流和錯誤流

System.in 從InputStream中繼承而來,用于從標(biāo)準(zhǔn)輸入設(shè)備中獲取輸入數(shù)據(jù)(通常是鍵盤)

System.out 從PrintStream 中繼承而來,把輸入送到缺省的顯示設(shè)備(通常是顯示器)

System.err 也是從PrintStream中繼承而來,把錯誤信息送到缺省的顯示設(shè)備(通常是顯示器)

每當(dāng)mian方法被執(zhí)行時,就會自動生產(chǎn)上述三個對象。這里就不再寫代碼驗證了。

內(nèi)存讀寫流

為了支持在內(nèi)存上的I/O,java.io 中提供了類;ByteArrayInputStream、ByteArrayOutputStream 和 StringBufferInputStream

  1. ByteArrayInputStream 可以從指定的字節(jié)數(shù)組中讀取數(shù)據(jù)
  2. ByteArrayOutputStream 中提供了 緩沖區(qū)可以存放數(shù)據(jù)(緩沖區(qū)大小可以在構(gòu)造方法中設(shè)定,缺省為32),可以用write() 方法 向其中寫入數(shù)據(jù),然后用toByArray() 方法將緩沖區(qū)中的有效字節(jié)寫到字節(jié)數(shù)組中去。size() 方法可以知道寫入的字節(jié)數(shù); reset() 可以丟棄所有內(nèi)容
  3. StringBufferInputStream 與 ByteArrayInputStream 相類似,不同點在于它是從字符緩沖區(qū) StringBuffer 中讀取 16位的 Unicode 數(shù)據(jù),而不是 8 位的字節(jié)數(shù)據(jù)(已被StringReader取代)

這里只做簡要的介紹,有興趣的同學(xué)可以查看一下這些類里具體的方法。

順序輸入流

java.io 中提供了類SequenceInputStream, 使應(yīng)用程序可以將幾個輸入流順序連接起來。順序輸入流提供了將多個不同的輸入流統(tǒng)一為一個輸入流的功能,這使得程序可能變得更加簡潔

例如:

FileInputStream f1,f2;
String s;
f1 = new FileInputStream("file1.txt");
f2 = new FileInputStream("file2.txt");
SequenceInputStream fs = new SequenceInputStream(f1,f2);
DataInputeStream ds = new DataInputStream(fs);
while((s = ds.readLine()) != null) {
    System.out.println(s);
}

參考連接

在線文檔-jdk-zh

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,406評論 6 538
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,034評論 3 423
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,413評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,449評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 72,165評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,559評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,606評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,781評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,327評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,084評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,278評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,849評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,495評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,927評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,172評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,010評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,241評論 2 375

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

  • IO簡單概述 IO解決問題 : 解決設(shè)備與設(shè)備之間的數(shù)據(jù)傳輸問題(硬盤 -> 內(nèi)存 內(nèi)存 -> 硬盤) 讀和寫文...
    奮斗的老王閱讀 3,454評論 0 53
  • # Java 流式輸入 輸出原理 # Java 流的分類 # 輸入 輸出 流 類 # 常見的節(jié)點流 和 處理流 #...
    時待吾閱讀 332評論 0 0
  • 流的基本概念 ??在java.io包中File類是唯一一個與文件本身有關(guān)的程序處理類,但是File只能操作文件本身...
    江湖非良人閱讀 861評論 0 1
  • CPU超頻# CPU超頻有倍頻和外頻兩個部分,而主頻等于倍頻乘以外頻,一般來說,超頻都是改倍頻,這樣比較安全,而外...
    lutery閱讀 3,688評論 0 0
  • 《吃魚》 一天,某安檢局的賈局長下班回到家,一家人正在吃晚飯時,聽到外面有人敲門,起身就去開了門,一看是所...
    游來游去的魚1240閱讀 230評論 3 3