您好,登錄后才能下訂單哦!
如何從下載文件數(shù)據(jù)丟失來分析BufferedOutputStream源碼,針對(duì)這個(gè)問題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問題的小伙伴找到更簡單易行的方法。
bis = new BufferedInputStream(new FileInputStream(targetFilePath)); bos = new BufferedOutputStream(response.getOutputStream()); byte[] buff = new byte[2048]; int bytesRead; while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) { bos.write(buff, 0, bytesRead); }
核心代碼非常簡單,就是根據(jù)目標(biāo)文件,通過FileInputStream流來讀取目標(biāo)文件流,寫入到response的輸出流中。中間通過BufferedInputStream和BufferedOutputStream緩沖流來提高性能。 根據(jù)上述代碼,我大膽猜測可能出現(xiàn)問題的原因是BufferedInputStream或者BufferedOutputStream。進(jìn)一步分析:
while (-1 != (bytesRead = bis.read(buff, 0, buff.length)))
該語句是循環(huán)讀取所有讀緩沖區(qū)的內(nèi)容,因此,該語句出現(xiàn)問題的幾率不是很大,很大可能是因?yàn)閷懢彌_區(qū)的問題,下面我通過分析BufferedOutputStream的源碼來看看能不能找出問題的原因:
BufferedOutputStream位于 java.io包下 /** * 繼承自FilterOutputStream(FilterOutputStream有一個(gè) OutputStream的屬性,就是目標(biāo)輸出out對(duì)象流) */ public class BufferedOutputStream extends FilterOutputStream { /** * 用來存儲(chǔ)數(shù)據(jù)的緩沖區(qū)(默認(rèn)8912個(gè)字節(jié)) */ protected byte buf[]; /** * 當(dāng)前已存儲(chǔ)數(shù)據(jù)的字節(jié)數(shù)(個(gè)人理解為指向已存儲(chǔ)數(shù)據(jù)末尾的一個(gè)指針) */ protected int count; /** * 構(gòu)造方法1: 用設(shè)置目標(biāo)輸出流對(duì)象,同時(shí)默認(rèn)buff緩沖區(qū)大小8912個(gè)字節(jié) */ public BufferedOutputStream(OutputStream out) { this(out, 8192); } /** * 構(gòu)造方法2:設(shè)置輸出流對(duì)象,自定義緩沖區(qū)的大小, */ public BufferedOutputStream(OutputStream out, int size) { super(out); if (size <= 0) { throw new IllegalArgumentException("Buffer size <= 0"); } buf = new byte[size]; } /** * 刷新緩沖區(qū)(將緩沖區(qū)內(nèi)容寫入到目標(biāo)流對(duì)象中,同同時(shí)將count置為0) **/ private void flushBuffer() throws IOException { if (count > 0) { out.write(buf, 0, count); count = 0; } } /** * 向緩沖區(qū)寫一個(gè)字節(jié)數(shù)據(jù) **/ public synchronized void write(int b) throws IOException { //先判斷緩沖區(qū)是否已滿,如果已滿,清空緩沖區(qū) if (count >= buf.length) { flushBuffer(); } buf[count++] = (byte)b; } /** * 向緩沖區(qū)寫入指定長度的數(shù)據(jù) **/ public synchronized void write(byte b[], int off, int len) throws IOException { //判斷寫入數(shù)據(jù)的長度是否超過緩沖區(qū)大小,如果超過,直接寫入目標(biāo)對(duì)象out流中,清空緩沖區(qū) if (len >= buf.length) { flushBuffer(); out.write(b, off, len); return; } //如果長度大于緩沖區(qū)剩余空間,將緩沖區(qū)清空,寫入數(shù)據(jù) if (len > buf.length - count) { flushBuffer(); } System.arraycopy(b, off, buf, count, len); count += len; } /** *刷新緩沖區(qū) **/ public synchronized void flush() throws IOException { flushBuffer(); out.flush(); } }
從上面的源碼中可以發(fā)現(xiàn):觸發(fā)緩沖區(qū)刷新的時(shí)機(jī)是當(dāng)寫入數(shù)據(jù)大小大于緩沖區(qū)的可用大小。
為了解決該問題,將核心操作放到try-catche-finally中,在finally中手動(dòng)關(guān)閉BufferedInputStream和BufferedOutputStream流(BufferedOutputStream并沒有close方法,調(diào)用父類FilterOutputStream的close方法),在關(guān)閉前會(huì)強(qiáng)制刷新緩沖區(qū)的數(shù)據(jù)到out寫對(duì)象流中。該問題得到解決。
關(guān)于如何從下載文件數(shù)據(jù)丟失來分析BufferedOutputStream源碼問題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識(shí)。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。