Java 基于字節(jié)的IO Byte Based IO 二進(jìn)制格式

更多 Java IO & NIO方面的文章,請(qǐng)參見(jiàn)文集《Java IO & NIO》


FileInputStream & FileOutputStream

讀寫(xiě)格式:按字節(jié)讀寫(xiě),每次讀寫(xiě)一個(gè)字節(jié),或者讀寫(xiě)一個(gè)字節(jié)數(shù)組。

public static void main(String[] args) throws Exception {
    InputStream fin = new FileInputStream("a.txt");
    OutputStream fout = new FileOutputStream("b.txt");

    System.out.println("How many bytes? = " + fin.available());

    int c;
    while((c = fin.read()) != -1) {
        System.out.print((char) c);

        fout.write(c);
    }
}

輸出:

How many bytes? = 12
Hello
World

使用緩沖流 BufferedInputStream & BufferedOutputStream

讀寫(xiě)格式:按字節(jié)讀寫(xiě),每次讀寫(xiě)一個(gè)字節(jié),或者讀寫(xiě)一個(gè)字節(jié)數(shù)組。

優(yōu)勢(shì):使用緩沖流,更節(jié)省時(shí)間,減少訪問(wèn)磁盤的數(shù)目
緩沖區(qū)默認(rèn)大小為 8M:private static int DEFAULT_BUFFER_SIZE = 8192;

public static void main(String[] args) throws Exception {
    InputStream fin = new FileInputStream("a.txt");
    BufferedInputStream bin = new BufferedInputStream(fin);

    OutputStream fout = new FileOutputStream("b.txt");
    BufferedOutputStream bout = new BufferedOutputStream(fout);

    System.out.println("How many bytes? = " + bin.available());

    // Read and Write by byte
    int c;
    while ((c = bin.read()) != -1) {
        System.out.print((char) c);

        bout.write(c);
    }

    // Read and Write by byte array
    byte[] buf = new byte[12];
    while (bin.read(buf) != -1) {
        for(byte b: buf)
            System.out.print((char) b);

        bout.write(buf);
    }
}

輸出:

How many bytes? = 12
Hello
World

FileInputStream VS BufferredInputStream

對(duì)比以上兩個(gè)例子:
一個(gè)使用 FileInputStream 來(lái)操作文件
另外一個(gè)使用 BufferredInputStream 來(lái)封裝 FileInputStream,然后操作文件。效率更高?。。?/strong>

原因分析:

FileInputStream 的 read 方法實(shí)現(xiàn)如下:
可以看出,實(shí)際上調(diào)用了一個(gè)本地方法,每次讀取一個(gè)字節(jié),都需要通過(guò) OS 來(lái)訪問(wèn)磁盤。

/**
 * Reads a byte of data from this input stream. This method blocks
 * if no input is yet available.
 *
 * @return     the next byte of data, or <code>-1</code> if the end of the
 *             file is reached.
 * @exception  IOException  if an I/O error occurs.
 */
public int read() throws IOException {
    return read0();
}

private native int read0() throws IOException;

BufferedInputStream 的 read 方法實(shí)現(xiàn)如下:
可以看出,BufferedInputStream 有一個(gè)緩沖區(qū),每次從磁盤中讀取 8M 的字節(jié),存儲(chǔ)到內(nèi)存緩沖區(qū)中,調(diào)用 read() 時(shí)實(shí)際上是讀取緩沖區(qū),無(wú)需訪問(wèn)磁盤。

public synchronized int read() throws IOException {
    if (pos >= count) {
        fill();
        if (pos >= count)
            return -1;
    }
    return getBufIfOpen()[pos++] & 0xff;
}

讀取具體數(shù)據(jù)類型 DateInputStream & DateOutputStream

讀寫(xiě)格式:按字節(jié)讀寫(xiě),按照具體的數(shù)據(jù)類型讀寫(xiě)特定數(shù)目的字節(jié):

  • readChar, writeChar:每次讀寫(xiě) 2 個(gè)字節(jié)
public final char readChar() throws IOException {
    int ch1 = in.read();
    int ch2 = in.read();
    if ((ch1 | ch2) < 0)
        throw new EOFException();
    return (char)((ch1 << 8) + (ch2 << 0));
}
public final void writeChar(int v) throws IOException {
    out.write((v >>> 8) & 0xFF);
    out.write((v >>> 0) & 0xFF);
    incCount(2);
}
  • readInt, writeInt:每次讀寫(xiě) 4 個(gè)字節(jié)
public final int readInt() throws IOException {
    int ch1 = in.read();
    int ch2 = in.read();
    int ch3 = in.read();
    int ch4 = in.read();
    if ((ch1 | ch2 | ch3 | ch4) < 0)
        throw new EOFException();
    return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
}
public final void writeInt(int v) throws IOException {
    out.write((v >>> 24) & 0xFF);
    out.write((v >>> 16) & 0xFF);
    out.write((v >>>  8) & 0xFF);
    out.write((v >>>  0) & 0xFF);
    incCount(4);
}
  • readDouble, writeDouble:每次讀寫(xiě) 8 個(gè)字節(jié)
  • readLong, writeLong:每次讀寫(xiě) 8 個(gè)字節(jié)
  • ...

DateInputStream & DateOutputStream 的使用:

public static void main(String[] args) throws Exception {
    OutputStream fout = new FileOutputStream("chars.txt");
    DataOutputStream dout = new DataOutputStream(fout);

    char chars[] = {'A', 'B', 'C', 'D'};
    for (int c : chars) {
        dout.writeChar(c);
    }
    dout.flush();

    InputStream fin = new FileInputStream("chars.txt");
    DataInputStream din = new DataInputStream(fin);
    char c;
    while (din.available() > 0) {
        c = din.readChar();
        System.out.print(c);
    }
}

輸出:

ABCD

注意事項(xiàng):
如下代碼會(huì)將 1 按照二進(jìn)制形式寫(xiě)入文件中,占據(jù) 4 bytes。
因此用記事本打開(kāi)該文本文件,其實(shí)無(wú)法看到數(shù)字 1。

int i = 1;
dout.writeInt(i);

讀取對(duì)象 ObjectInputStream & ObjectOutputStream

讀寫(xiě)格式:按字節(jié)讀寫(xiě),讀寫(xiě)的對(duì)象需要實(shí)現(xiàn) Serializable 接口。

ObjectInputStream & ObjectOutputStream 的使用:

public class Stream_Object_Test {

    public static void main(String[] args) throws Exception {
        OutputStream fout = new FileOutputStream("people.txt");
        ObjectOutputStream oout = new ObjectOutputStream(fout);

        People p = new People("Tom", 20);
        oout.writeObject(p);

        InputStream fin = new FileInputStream("people.txt");
        ObjectInputStream oin = new ObjectInputStream(fin);
        People new_p = (People) oin.readObject();
        System.out.println(new_p.getName() + " " + new_p.getAge());
    }
}

class People implements Serializable {
    private String name;
    private int age;

    People(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
最后編輯于
?著作權(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)容

  • 1 IO(三)No20 1.1Properties 屬性集 【 Properties屬性集,主要用于操作配置屬...
    征程_Journey閱讀 963評(píng)論 0 1
  • 之所以寫(xiě)這個(gè)是因?yàn)镠adoop的IO與·這個(gè)類似 但要比這個(gè)深入,而且都還涉及到網(wǎng)絡(luò)傳輸原理的五個(gè)層次。所以,一...
    起個(gè)什么呢稱呢閱讀 1,139評(píng)論 0 6
  • IO簡(jiǎn)單概述 IO解決問(wèn)題 : 解決設(shè)備與設(shè)備之間的數(shù)據(jù)傳輸問(wèn)題(硬盤 -> 內(nèi)存 內(nèi)存 -> 硬盤) 讀和寫(xiě)文...
    奮斗的老王閱讀 3,542評(píng)論 0 53
  • 1 IONo18 1.1IO框架 【 IO:Input Output 在程序運(yùn)行的過(guò)程中,可能需要對(duì)一些設(shè)備進(jìn)...
    征程_Journey閱讀 1,030評(píng)論 0 1
  • 我們?cè)陂_(kāi)發(fā)中常常需要利用一些假數(shù)據(jù)來(lái)做測(cè)試,這種時(shí)候就可以使用 Faker 來(lái)偽造數(shù)據(jù)從而用來(lái)測(cè)試. Faker ...
    hjqjk閱讀 19,804評(píng)論 1 18

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