深入研究IO-BufferedOutputStream的坑

目錄

1.實戰:複製文件

2.OutputStream的緩存器(自定義數組)與BufferedOutputStream中的緩存器(數組)區別


要介紹BufferedOutputStream的坑,我們先了解一下OutputStream類 
抽象類OutputStream類有三個write方法

public abstract void write(int b)

public void write(byte b[])

public void write(byte b[], int off, int len)

由上面我們可以看出第一個write方法是讓子類覆蓋的,而第二個人write(byte b[])方法源代碼如下

public void write(byte b[]) throws IOException {

        write(b, 0, b.length);

    }

所以可見最後處理還是調用第三個方法write(byte b[],int off,int len)                                                          

1.實戰:複製文件

public class TestCopyFile {

    public static void main(String[] args) throws IOException {

       String filePath = "F:/123.png";

       String filePath2 = "F:/abc.png";

       File file = new File(filePath);

       File file2 = new File(filePath2);

       copyFile(file, file2);

    }

原文:https://blog.csdn.net/lan861698789/article/details/81380409

    public static void copyFile(File oldFile, File newFile) {

       InputStream inputStream = null;

       BufferedInputStream bufferedInputStream = null;

       OutputStream outputStream = null;

       BufferedOutputStream bufferedOutputStream = null;

       try {

           inputStream = new FileInputStream(oldFile);

           bufferedInputStream = new BufferedInputStream(inputStream);

           outputStream = new FileOutputStream(newFile);

           bufferedOutputStream = new BufferedOutputStream(outputStream);

 

           byte[] b = new byte[1024]; // 1代表一次最多讀取1KB的內容

           int length = 0; // 代表實際讀取的字節數

           while ((length = bufferedInputStream.read(b)) != -1) {

              bufferedOutputStream.write(b, 0, length);

           }

           bufferedOutputStream.flush();// 緩衝區的內容寫入到文件

       } catch (Exception e) {

           e.printStackTrace();

       } finally {

           //......省略

       }

    }

}

注意:上面黃顏色1地方的b數組,不能大於8kb,否則buffer就沒意義了。這就是使用BufferedOutputStream的弊端

2.OutputStream的緩存器(自定義數組)與BufferedOutputStream中的緩存器(數組)區別

看BufferedInputStream源碼:

public class BufferedOutputStream extends FilterOutputStream {

    protected byte buf[];// 這兒定義了一個byte[]數組,用來充當緩存器

    protected int count; // 這個變量是重點,他就是用來記錄當前緩存器中的字節數量的

    public BufferedOutputStream(OutputStream out) {// 我們初始化創建一個對象的時候給了這個buf這個數組8192個字節.8KB

       this(out, 8192);

    }

 

    public BufferedOutputStream(OutputStream out, int size) {

       super(out);

       buf = new byte[size]; // 這兒創建一個給定大小的數組對象來充當緩存器

    }

 

    public synchronized void write(int b) throws IOException {

       if (count >= buf.length) {

           flushBuffer();

       }

       buf[count++] = (byte) b;

    }

原文:https://blog.csdn.net/lan861698789/article/details/81380409

    // 該方法是重點

public synchronized void write(byte b[], int off, int len) throws IOException {

        //如果傳進來的數組長度大於buf 數組的長度,則直接調用OutputStream對象的write方法。

        if (len >= buf.length) {

            flushBuffer();

            out.write(b, off, len);

            return;

        }

        //驗證BufferedOutputStream 類中buf剩下的空間能否裝得下傳進來的數組。如果不能則先將當前buf數組中數據寫入底層io流中

        if (len > buf.length - count) {

            flushBuffer();

        }

        //該處是重點,如果在當前BufferedOutputStream 類中buf數組沒有滿,則將傳進來的數組複製到當前類對象buf數組中,同時更新count的值。

        System.arraycopy(b, off, buf, count, len);

        count += len;

}

   //調用flushBuffer方法也就是將不滿8192個字節數組中的數據發送出去。同時將count置零。

    private void flushBuffer() throws IOException {

       if (count > 0) {

           out.write(buf, 0, count);

           count = 0;

       }

    }

    // 強制將buf數據中未滿8192個字節的數據寫入底層io中。

    public synchronized void flush() throws IOException {

       flushBuffer();

       out.flush();

    }

}

結論: 
OutputStream的緩存器(數組)與BufferedOutputStream中類的緩存器(數組)本質是一樣的。

區別:

優點:

只是BufferedOutputStream類中將要寫入到底層io流中的數據先湊個整,然後再一起寫入底層io流中,這樣就大大節省了io操作,大大提高了io利用率,寫一次io是很費資源的。

原文:https://blog.csdn.net/lan861698789/article/details/81380409

缺點:

1.如果要寫入的size沒有buf大,然後如果buf沒有滿,則會把當前數組的值複製到buf裏面,多了很多複製的操作。

2.如果要寫入的size大於buf,則直接將全部數據寫入IO。那麼感覺使用BufferedOutputStream的意義就沒有了。感覺只有當要寫入的size遠小於buf時候,纔有意義。

2.這樣也出現了一個問題,假設向硬盤中寫入一個文件,文件最後數據比默認值8192個字節小,則BufferOutputStream就不會將這些數據寫入底層io流中,造成文件缺失,因此就需要在close()前調用flush()方法,強制將還沒有裝滿buf數組的數據寫入底層io中。

原文:https://blog.csdn.net/lan861698789/article/details/81380409

總結:建議使用outputStream,然後自定義數組來存放緩存。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章