最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java BufferedOutputStream類的常用方法講解

 更新時間:2021年10月12日 11:41:33   作者:scbiaosdo  
這篇文章主要介紹了Java BufferedOutputStream類的常用方法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

BufferedOutputStream類的常用方法

BufferedOutputStream字節(jié)緩沖輸出流

構(gòu)造方式

第一種開發(fā)中

public BufferedOutputStream(OutputStream out)

采用的默認的緩沖區(qū)大小(足夠大了) ,來構(gòu)造一個字節(jié)緩沖輸出流對象

public BufferedOutputStream(OutputStream out,int size)

指定size緩沖區(qū)大小構(gòu)造緩沖輸出流對象

IllegalArgumentException - 如果 size <= 0

常用方法

public void write(int b)throws IOException

一次寫一個字節(jié)

  • b - 要寫入的字節(jié)。
public void write(byte[] b,int off,int len) throws IOException

一次寫一個字節(jié)數(shù)組的一部分

  • b - 數(shù)據(jù)。
  • off - 數(shù)據(jù)的起始偏移量。
  • len - 要寫入的字節(jié)數(shù)。
public void flush() throws IOException

刷新此緩沖的輸出流。這迫使所有緩沖的輸出字節(jié)被寫出到底層輸出流中。

public void close() throws IOException

關(guān)閉此輸出流并釋放與此流有關(guān)的所有系統(tǒng)資源。

FilterOutputStream 的 close 方法先調(diào)用其 flush 方法,然后調(diào)用其基礎(chǔ)輸出流的 close 方法。

程序示例

public static void main(String[] args) throws Exception {    
    //符合Java一種設(shè)計模式:裝飾者設(shè)計模式(過濾器:Filter)
    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("bos.txt")) ;        
    //寫數(shù)據(jù)
    bos.write("hello".getBytes());
    //釋放資源
    bos.close();
}

BufferedOutputStream深入分析

FileOutputStream和BufferedOutputStream都提供了一系列的將數(shù)據(jù)寫入文件的方式,并且我們都知道BufferedOutputStream要比直接使用FileOutputStream寫入速度要快,本文通過案例實際演示一下兩者的區(qū)別。

代碼準備

public class BufferFile {
    public static void main(String[] args) {
        //每次向文件中寫入一個8字節(jié)的數(shù)組
        byte[] bytes = "1234567\n".getBytes();
        //每隔100毫秒通過buffer的方式向文件中寫入數(shù)據(jù)
        new Thread(() -> {
            System.out.println("buffer_while start...");
            File file = new File("/var/file_test_data/out_buffer_while.txt");
            FileOutputStream fileOutputStream;
            try {
                fileOutputStream = new FileOutputStream(file);
                BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
                while (true) {
                    Thread.sleep(100);
                    bufferedOutputStream.write(bytes);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
        //通過buffer的方式向文件中寫入1千萬次
        new Thread(() -> {
            System.out.println("buffer_for start...");
            File file = new File("/var/file_test_data/out_buffer_for.txt");
            FileOutputStream fileOutputStream;
            try {
                fileOutputStream = new FileOutputStream(file);
                BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
                for (int i = 0; i < 10000000; i++) {
                    bufferedOutputStream.write(bytes);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(new Date() + ": buffer_for end...");
        }).start();
        //通過file的方式向文件中寫入1千萬次
        new Thread(() -> {
            System.out.println("file_for start...");
            File file = new File("/var/file_test_data/out_file_for.txt");
            FileOutputStream fileOutputStream;
            try {
                fileOutputStream = new FileOutputStream(file);
                for (int i = 0; i < 10000000; i++) {
                    fileOutputStream.write(bytes);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(new Date() + ": file_for end...");
        }).start();
    }
}

開始運行

在這里插入圖片描述

強行停止后的運行結(jié)果

在這里插入圖片描述

1、file和buffe寫入速度比較

兩者分別寫入1千萬次,時間上buffer比file快8秒,如果當寫入次數(shù)指數(shù)級增加時,buffer的優(yōu)勢將更加明顯。

2、數(shù)據(jù)寫入完整性問題

buffer雖然要比file快,但是從最終數(shù)據(jù)上可以看出,buffer會丟數(shù)據(jù)

  • 當?shù)谝粋€線程寫入時數(shù)據(jù)還未滿8kb時,強制停止java進程,最終out_buffer_while.txt沒有數(shù)據(jù)。
  • 第二個線程,雖然最終代碼執(zhí)行完畢,但是比較file方式,out_buffer_for.txt文件看起來也丟了一部分數(shù)據(jù)。

原因分析

當使用buffer讀寫文件時,數(shù)據(jù)并沒有直接被寫入磁盤,而是被緩存到一個字節(jié)數(shù)據(jù)中,這個字節(jié)數(shù)組的大小是8kb,默認情況下只有當8kb被填充滿了以后,數(shù)據(jù)才會被一次性寫入磁盤,這樣一來就大大減少了系統(tǒng)調(diào)用的次數(shù)(file是每一次write都會產(chǎn)生系統(tǒng)調(diào)用),當然也正是因為buffer中的每一次write只是寫入到內(nèi)存中(JVM自身內(nèi)存中),所以當數(shù)據(jù)未寫入磁盤前,如果JVM進程掛了,那么就會造成數(shù)據(jù)丟失。

手動刷盤

為了解決數(shù)據(jù)丟失的問題,buf中提供了flush()方法,用戶可以自行決定合適將數(shù)據(jù)刷寫到磁盤中

  • 如果你的flush()調(diào)用的非常頻繁,那就會退化為普通的file模式了。
  • 如果你的flush()調(diào)用的又不太頻繁,那么丟數(shù)據(jù)的可能性就比較高。
  • 無論如何業(yè)務(wù)邏輯中數(shù)據(jù)寫完時,一定要調(diào)用一次flush(),確保緩沖區(qū)的數(shù)據(jù)刷到磁盤上。

將無限循環(huán)寫入的代碼注釋掉,在buf寫1千萬完成后,加上bufferedOutputStream.flush();

public class BufferFile {
    public static void main(String[] args) {
        //每次向文件中寫入一個8字節(jié)的數(shù)組
        byte[] bytes = "1234567\n".getBytes();
        //每隔100毫秒通過buffer的方式向文件中寫入數(shù)據(jù)
        /*new Thread(() -> {
            System.out.println("buffer_while start...");
            File file = new File("/var/file_test_data/out_buffer_while.txt");
            FileOutputStream fileOutputStream;
            try {
                fileOutputStream = new FileOutputStream(file);
                BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
                while (true) {
                    Thread.sleep(100);
                    bufferedOutputStream.write(bytes);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();*/
        //通過buffer的方式向文件中寫入1千萬次
        new Thread(() -> {
            System.out.println("buffer_for start...");
            File file = new File("/var/file_test_data/out_buffer_for.txt");
            FileOutputStream fileOutputStream;
            try {
                fileOutputStream = new FileOutputStream(file);
                BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
                for (int i = 0; i < 10000000; i++) {
                    bufferedOutputStream.write(bytes);
                }
                bufferedOutputStream.flush();
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(new Date() + ": buffer_for end...");
        }).start();
        //通過file的方式向文件中寫入1千萬次
        new Thread(() -> {
            System.out.println("file_for start...");
            File file = new File("/var/file_test_data/out_file_for.txt");
            FileOutputStream fileOutputStream;
            try {
                fileOutputStream = new FileOutputStream(file);
                for (int i = 0; i < 10000000; i++) {
                    fileOutputStream.write(bytes);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(new Date() + ": file_for end...");
        }).start();
    }
}

這次再看數(shù)據(jù)寫入完整了

在這里插入圖片描述

buffer源碼分析

類的機構(gòu)圖

在這里插入圖片描述

首先當創(chuàng)建一個BufferedOutputStream對象時,構(gòu)造方法就初始化了緩沖的字節(jié)數(shù)組大小為8kb

	protected byte buf[];
    public BufferedOutputStream(OutputStream out) {
        this(out, 8192);
    }
    public BufferedOutputStream(OutputStream out, int size) {
        super(out);
        if (size <= 0) {
            throw new IllegalArgumentException("Buffer size <= 0");
        }
        buf = new byte[size];
    }

當調(diào)用buffer.write(b)時,調(diào)用的是父類FilterOutputStream的方法

    public void write(byte b[]) throws IOException {
    	//寫入的字節(jié)數(shù)組b,從0開始,一共要寫入的長度
        write(b, 0, b.length);
    }
    	
    public void write(byte b[], int off, int len) throws IOException {
        if ((off | len | (b.length - (len + off)) | (off + len)) < 0)
            throw new IndexOutOfBoundsException();
		//遍歷數(shù)組,一個字節(jié)一個字節(jié)的把數(shù)據(jù)寫入數(shù)組中
        for (int i = 0 ; i < len ; i++) {
            write(b[off + i]);
        }
    }
    
    public synchronized void write(int b) throws IOException {
    	//判斷字節(jié)長度是否超過buf.length,buf在初始化已經(jīng)指定大小為8192,即8kb
    	//如果超過則調(diào)用flushBuffer
        if (count >= buf.length) {
            flushBuffer();
        }
        把每一個字節(jié)寫入緩沖的buf數(shù)組中,并且統(tǒng)計值count++
        buf[count++] = (byte)b;
    }
    private void flushBuffer() throws IOException {
        if (count > 0) {
        	//真正的調(diào)用OutputStream,寫入數(shù)據(jù)到磁盤中
        	//寫入buf緩沖字節(jié)數(shù)組數(shù)據(jù),從0下標開始,一直寫到count,即有多少寫多少。
            out.write(buf, 0, count);
            count = 0;
        }
    }

關(guān)于buf緩沖數(shù)據(jù)大小設(shè)置

buffer提供了可以自定義緩沖大小的構(gòu)造方法

    public BufferedOutputStream(OutputStream out, int size) {
        super(out);
        if (size <= 0) {
            throw new IllegalArgumentException("Buffer size <= 0");
        }
        buf = new byte[size];
    }

如果緩沖大小設(shè)置的比較大。

  • 好處:進一步減少調(diào)用系統(tǒng)內(nèi)核寫數(shù)據(jù)的方法,提高寫入速度,kafka的批寫入默認就是16kb寫一次。
  • 壞處:1、丟失的數(shù)據(jù)可能會更多,2、要注意堆內(nèi)存的消耗。

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 通過實例學(xué)習(xí)JAVA對象轉(zhuǎn)成XML輸出

    通過實例學(xué)習(xí)JAVA對象轉(zhuǎn)成XML輸出

    這篇文章主要介紹了通過實例學(xué)習(xí)JAVA對象轉(zhuǎn)成XML輸出,做流程圖的項目時,新的流程定義為xml的,需要對xml與java對象進行互轉(zhuǎn),下面我們來深入學(xué)習(xí),需要的朋友可以參考下
    2019-06-06
  • 基于Java和XxlCrawler獲取各城市月度天氣情況實踐分享

    基于Java和XxlCrawler獲取各城市月度天氣情況實踐分享

    本文主要講解使用Java開發(fā)語言,使用XxlCrawler框架進行智能的某城市月度天氣抓取實踐開發(fā),文章首先介紹目標網(wǎng)站的相關(guān)頁面及目標數(shù)據(jù)的元素,然后講解在信息獲取過程的一些參數(shù)配置以及問題應(yīng)對,需要的朋友可以參考下
    2024-05-05
  • 關(guān)于@RequestParam的使用所遇到的404問題

    關(guān)于@RequestParam的使用所遇到的404問題

    這篇文章主要介紹了關(guān)于@RequestParam的使用所遇到的404問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • spring boot集成rabbitmq的實例教程

    spring boot集成rabbitmq的實例教程

    這篇文章主要給大家介紹了關(guān)于spring boot集成rabbitmq的相關(guān)資料,springboot集成RabbitMQ非常簡單,文中通過示例代碼介紹的非常詳細,需要的朋友們可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-11-11
  • springMVC返回復(fù)雜的json格式數(shù)據(jù)方法

    springMVC返回復(fù)雜的json格式數(shù)據(jù)方法

    下面小編就為大家分享一篇springMVC返回復(fù)雜的json格式數(shù)據(jù)方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-03-03
  • 一文講解Java的String、StringBuffer和StringBuilder的使用與區(qū)別

    一文講解Java的String、StringBuffer和StringBuilder的使用與區(qū)別

    String是不可變的字符序列,而StringBuffer和StringBuilder是可變的字符序列,本文就來詳細的介紹一下Java的String、StringBuffer和StringBuilder的使用與區(qū)別,感興趣的可以了解一下
    2024-03-03
  • 如何配置cursor進行Java springboot項目開發(fā)

    如何配置cursor進行Java springboot項目開發(fā)

    本文介紹了如何在Cursor IDE中配置Java和Spring Boot項目開發(fā)環(huán)境,首先,設(shè)置了系統(tǒng)用戶級別的JDK配置,以便在多個項目之間切換時不需要重新配置,然后,配置了Gradle環(huán)境變量,并安裝了必要的Java開發(fā)插件,感興趣的朋友跟隨小編一起看看
    2025-02-02
  • java中字符串如何計算字節(jié)長度

    java中字符串如何計算字節(jié)長度

    這篇文章主要介紹了java中字符串如何計算字節(jié)長度,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • 關(guān)于@Autowired的使用及注意事項

    關(guān)于@Autowired的使用及注意事項

    這篇文章主要介紹了關(guān)于@Autowired的使用及注意事項,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • Java基于Guava Retrying實現(xiàn)重試功能

    Java基于Guava Retrying實現(xiàn)重試功能

    這篇文章主要介紹了Java基于Guava Retrying實現(xiàn)重試功能,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-07-07

最新評論

镇康县| 凤山市| 乐清市| 德州市| 皮山县| 温泉县| 临泽县| 泽库县| 调兵山市| 星子县| 明水县| 禄劝| 秦皇岛市| 青海省| 梁河县| 铜梁县| 德保县| 新昌县| 财经| 石阡县| 抚州市| 如东县| 莎车县| 中牟县| 新宾| 宁德市| 涞源县| 邵阳县| 永年县| 永顺县| 都安| 石台县| 镇宁| 嵊州市| 梓潼县| 盘锦市| 罗田县| 姚安县| 长乐市| 梧州市| 凤冈县|