Java中IO流的BufferedOutputStream和FileOutputStream對比
FilteOutputStream
不帶緩沖的操作(FilteOutputStream
類和FilteInputStream
類),每讀一個字節(jié)就要寫入一個字節(jié),由于涉及磁盤的IO操作相比內存的操作要慢很多,所以在讀寫的字節(jié)比較少的情況下,效率比較低;
FileOutputStream fileOutputStream = new FileOutputStream("D:\\1.txt");
BufferedOutputStream
BufferedOutputStream是帶緩沖區(qū)的輸出流,不管是BufferedOutputStream
還是BufferedInputStream
里面都自帶了默認緩沖區(qū),大小是8192Byte,也就是8KB ,能夠減少訪問磁盤的次數(shù),提高文件讀取性能;它們都用到了裝飾器模式;將FilteOutputStream
裝到里面,所以 BufferedOutputStream
是 依賴FilteOutputStream
的;
當傳輸?shù)奈募貏e大的時候,BufferInputStream
的優(yōu)點就體現(xiàn)出來了 ,帶緩沖的流,可以一次讀很多字節(jié),但不向磁盤中寫入,只是先放到內存里。等湊夠了緩沖區(qū)大小(默認8KB)的時候一次性寫入磁盤,這種方式可以減少磁盤操作次數(shù),速度就會提高很多!這就是兩者的區(qū)別
BufferedOutputStream什么時候會往磁盤中寫數(shù)據(jù)呢?
- 第①種:緩存區(qū)滿了,寫出去!
- 第②種:
flush()
方法被調用,寫出去! - 第③種:
close()
方法被調用,寫出去!
因為,close()
方法被調用的時候,會先調用flush()
方法。
如何設置緩沖區(qū)大小
看到了嗎?構造方法的第二個參數(shù)就是緩沖區(qū)大小,可以自己自行配置,默認的size就是8192,也就是8kb。
// out 寫 BufferedOutputStream in = new BufferedOutputStream(new FileOutputStream("D:\\out.txt"),8192); // in 讀 BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("D:\\in.txt"),8192);
區(qū)別
通過介紹,對它們內部的也就有了一定的了解了;
BufferedOutputStream 真的比 FileOutputStream 快嗎?
為了驗證這個這個問題,我們需要做兩輪測試,通過寫入少量的數(shù)據(jù)和大量數(shù)據(jù)對比一下它們之間的速度如何;
第一輪測試 :每次只寫一個字節(jié)
這一輪測試里面,會延時5秒,在這5秒內不停地往文件中寫入一個字節(jié)的數(shù)據(jù);我們看看5秒后BufferedOutputStream 和 FileOutputStream 能寫多少數(shù)據(jù),代碼如下,(注意:這2個測試方法用到了一個共享變量run
,所以測試時一定要分開運行,千萬不可以一起運行這個2個測試方法,否則測試數(shù)據(jù)不準確)
volatile boolean run = true; // 標志位 // 不帶緩沖區(qū) 每次只寫一個字節(jié) @Test public void fileWriteOneByte() throws IOException { FileOutputStream fileOutputStream = new FileOutputStream("D:\\FileOutputStream_one.txt"); // 延時5秒 fiveSeconds(); while (run){ // 每次寫一個字節(jié) fileOutputStream.write(1); } fileOutputStream.flush(); fileOutputStream.close(); } // 帶緩沖區(qū)-->每次只寫一個字節(jié) @Test public void bufferWriteOneByte() throws IOException { FileOutputStream fileOutputStream = new FileOutputStream("D:\\BufferedOutputStream_one.txt"); BufferedOutputStream bufferedInputStream = new BufferedOutputStream(fileOutputStream); // 延時5秒 fiveSeconds(); while (run){ // 每次寫一個字節(jié) bufferedInputStream.write((byte)1); } bufferedInputStream.flush(); bufferedInputStream.close(); } /** * 延時5秒 */ private void fiveSeconds(){ new Thread(new Runnable() { @Override public void run() { try { // 睡5秒 Thread.sleep(5000); // 跳出死循環(huán) run = false; } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); }
運行后,我們看看結果,顯而易見,帶緩沖區(qū)的BufferedOutputStream
在5秒內寫入了300M的數(shù)據(jù),而不帶緩沖區(qū)的FileOutputStream
在5秒內只寫入了1.71M的數(shù)據(jù);這個讀寫速度對比,簡直就是碾壓型的;
所以我宣布,第一輪 帶緩沖區(qū)的BufferedOutputStream
獲勝!?。?/p>
第二輪測試:每次寫入81920個字節(jié)(80KB)
這一次我們加大量級,當它們每次都寫入81920
個字節(jié)時,也就是80K,看看這2種方式在5秒內能寫多少數(shù)據(jù),寫的速度會有什么變化呢?誰寫的更多呢?讓我們拭目以待,上代碼 (注意:這2個測試方法用到了一個共享變量run
,所以測試時一定要分開運行,千萬不可以一起運行這個2個測試方法,否則測試數(shù)據(jù)不準確)
volatile boolean run = true; // 每次寫81920個字節(jié) @Test public void file() throws IOException { byte[] bytes = new byte[81920]; FileOutputStream fileOutputStream = new FileOutputStream("D:\\FileOutputStream_81920.txt"); // 延時5秒 fiveSeconds(); while (run){ // 每次寫入 81920 個字節(jié) fileOutputStream.write(bytes); } fileOutputStream.flush(); fileOutputStream.close(); } // 每次寫81920個字節(jié) @Test public void bufferFile() throws IOException { byte[] bytes = new byte[81920]; FileOutputStream fileOutputStream = new FileOutputStream("D:\\BufferedOutputStream_81920.txt"); BufferedOutputStream bufferedInputStream = new BufferedOutputStream(fileOutputStream,81920); // 延時5秒 fiveSeconds(); while (run){ // 每次寫入 81920 個字節(jié) bufferedInputStream.write(bytes); } bufferedInputStream.flush(); bufferedInputStream.close(); } // 延時5秒 private void fiveSeconds(){ new Thread(new Runnable() { @Override public void run() { try { // 睡5秒 Thread.sleep(5000); // 跳出死循環(huán) run = false; } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); }
通過結構可以看到,帶緩沖區(qū)的BufferedOutputStream
在5秒內寫入了將近4.5G
的數(shù)據(jù),而不帶緩沖區(qū)的FileOutputStream
在5秒內寫入了 6.87G
的數(shù)據(jù), FileOutputStream 反而更快了;
所以我宣布,第二輪 不帶緩沖區(qū)的FileOutputStream
獲勝?。?!
結論
通過以上的數(shù)據(jù)可以得出結論,誰快誰慢是根據(jù)實際情況來決定的,而不是說帶了緩沖區(qū)就一定快;
- 每次寫入的數(shù)據(jù)量小的情況下,帶緩沖區(qū)的
BufferedOutputStream
效率更快; - 每次寫入的數(shù)據(jù)量比較大時,不帶緩沖區(qū)的
FileOutputStream
效率更快;
所以,大家在選擇的時候就需要根據(jù)實際情況來決定使用哪種IO流了,而大部分情況下,FileOutputStream
就已經(jīng)足夠了,只需要將寫入的數(shù)據(jù)量大一點即可;
到此這篇關于Java中IO流的BufferedOutputStream和FileOutputStream對比的文章就介紹到這了,更多相關Java的IO流BufferedOutputStream內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
springboot中RestTemplate配置HttpClient連接池詳解
這篇文章主要介紹了springboot中RestTemplate配置HttpClient連接池詳解,這些Http連接工具,使用起來都比較復雜,如果項目中使用的是Spring框架,可以使用Spring自帶的RestTemplate來進行Http連接請求,需要的朋友可以參考下2023-11-11Java利用MessageFormat實現(xiàn)短信模板的匹配
這篇文章主要介紹了Java利用MessageFormat實現(xiàn)短信模板的匹配,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-06-06springboot中報錯Invalid character found in
這篇文章主要介紹了springboot中報錯Invalid character found in the request的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09Java中增強for循環(huán)的實現(xiàn)原理和坑詳解
增強的for循環(huán)是在傳統(tǒng)的for循環(huán)中增加的強大的迭代功能的循環(huán),是在jdk1.5之后提出來的。下面這篇文章主要給大家介紹了關于Java中增強for循環(huán)的實現(xiàn)原理和坑的相關資料,需要的朋友可以參考下2018-04-04