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是從裝置來(lái)源地讀取數(shù)據(jù)的抽象表示,例如System中的標(biāo)準(zhǔn)輸入流in對(duì)象就是一個(gè)InputStream類型的實(shí)例。

我們先來(lái)看看InputStream類的方法:

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

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

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

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

OutputStream

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

OutputStream 類方法:

方法 說(shuō)明
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 個(gè)字節(jié)寫入此輸出流
flush()throws IOException 刷新此輸出流并強(qiáng)制寫出所有緩沖的輸出字節(jié)
close()throws IOException 關(guān)閉流

看個(gè)例子

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 是一個(gè)字節(jié)一個(gè)字節(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 處理中,最常見(jiàn)的就是對(duì)文件的操作。java.io 包中所提供的文件操作類包括

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

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

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

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

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

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

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

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

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

//創(chuàng)建一個(gè)文件路徑名為 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 沒(méi)有,系統(tǒng)可以創(chuàng)建,在 workspace 的 Test 項(xiàng)目下可以找到
            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 實(shí)現(xiàn)了帶緩沖的過(guò)濾流,它提供了緩沖機(jī)制,把任意的I/O流“捆綁”到緩沖流上,可以提高I/O流的讀取效率

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

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

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

構(gòu)造方法:


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

舉個(gè)例子,將緩沖流與文件流相接

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 中得到的是實(shí)際讀取的長(zhǎng)度,bArray 中得到的是數(shù)據(jù)

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

對(duì)于 BufferedOutputStream,只有緩沖區(qū)滿時(shí),才會(huì)將數(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è)計(jì)了一種較為高級(jí)的數(shù)據(jù)輸入輸出方式:除了可處理字節(jié)和字節(jié)數(shù)組外,還可以處理 int、float、boolean 等基本數(shù)據(jù)類型,這些數(shù)據(jù)在文件中的表示方式和它們?cè)趦?nèi)存中的一樣,無(wú)須轉(zhuǎn)換,如 read(), readInt(), readByte()...; write(), writeChar(), writeBoolean()... 此外,還可以用 readLine() 方法讀取一行信息。

方法 :

方法 返回值 說(shuō)明
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é),并將它們存儲(chǔ)在緩沖區(qū)數(shù)組b中
reaFully(byte[] b, int off, int len) void 從輸入流中讀取len個(gè)字節(jié)
skipBytes(int n) int 與InputStream.skip 等價(jià)
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 只輸出每個(gè)字符的低 8 位;不完全支持 UNICODE
writeChars(String s) void 每個(gè)字符在輸出中都占兩個(gè)字節(jié)

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

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

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

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

接下來(lái)我們通過(guò)具體的代碼,看一看它的用法吧;

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)流

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

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

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

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

每當(dāng)mian方法被執(zhí)行時(shí),就會(huì)自動(dòng)生產(chǎn)上述三個(gè)對(duì)象。這里就不再寫代碼驗(yà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 相類似,不同點(diǎn)在于它是從字符緩沖區(qū) StringBuffer 中讀取 16位的 Unicode 數(shù)據(jù),而不是 8 位的字節(jié)數(shù)據(jù)(已被StringReader取代)

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

順序輸入流

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

例如:

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)容合作請(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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

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