摘要:引語(yǔ)之前做項(xiàng)目的時(shí)候遇到一個(gè)問(wèn)題就是從網(wǎng)絡(luò)中讀取的圖片要上傳到而且要對(duì)圖片進(jìn)行裁剪和壓縮其中上傳和裁剪都要使用到圖片的又因?yàn)椴荒苤貜?fù)讀導(dǎo)致裁剪是成功的而上傳是失敗的我們今天就提供兩種方法來(lái)解決不能重復(fù)讀的問(wèn)題問(wèn)題分析的內(nèi)部有個(gè)指針當(dāng)讀取的時(shí)
引語(yǔ):
????之前做項(xiàng)目的時(shí)候遇到一個(gè)問(wèn)題,就是從網(wǎng)絡(luò)中讀取的圖片要上傳到oss,而且要對(duì)圖片進(jìn)行裁剪和壓縮,其中上傳和裁剪都要使用到圖片的inputStream,
又因?yàn)閕nputstream不能重復(fù)讀,導(dǎo)致裁剪是成功的,而上傳是失敗的.我們今天就提供兩種方法來(lái)解決,inputStream不能重復(fù)讀的問(wèn)題.
inputStream的內(nèi)部有個(gè)pos指針,當(dāng)讀取的時(shí)候指針會(huì)不斷的移動(dòng),當(dāng)移動(dòng)到末尾的時(shí)候,就無(wú)法再次讀取了.
我們寫(xiě)個(gè)簡(jiǎn)單的例子來(lái)看下:
String text = "測(cè)試inputStream內(nèi)容"; InputStream inputStream = new ByteArrayInputStream(text.getBytes()); byte[] readArray = new byte[inputStream.available()]; int readCount1 = inputStream.read(readArray); System.out.println("讀取了" + readCount1 + "個(gè)字節(jié)"); byte[] readArray2 = new byte[inputStream.available()]; int readCount2 = inputStream.read(readArray2); System.out.println("讀取了" + readCount2 + "個(gè)字節(jié)"); /** * 執(zhí)行結(jié)果是 * 讀取了23個(gè)字節(jié) * 讀取了-1個(gè)字節(jié) */
從執(zhí)行結(jié)果可以看出確實(shí)inputstream的設(shè)計(jì)是只能讀取一次.
注意: 這里稍微提一下inputStream.available()這個(gè)方法,本地的文件可以直接知道文件的大小,但是如果是網(wǎng)絡(luò)中的數(shù)據(jù),這個(gè)方法最好不要用,因?yàn)閭鬏數(shù)臅r(shí)候不是連續(xù)的,數(shù)據(jù)的大小會(huì)讀取不準(zhǔn)
那么我們實(shí)際項(xiàng)目中應(yīng)該怎么解決呢?總不能就真的只使用一次inputSteam吧.我們來(lái)看解決方法:
方法一:
使用ByteArrayOutputStream來(lái)緩存字節(jié),然后每次讀取從緩存的ByteArrayOutputStream中拿取.
很自然的想到把inputStream的緩存起來(lái)(當(dāng)然不一定說(shuō)是要放在ByteArrayOutputStream,其他的方式也可以,都是緩存起來(lái)的思路,實(shí)現(xiàn)方式有很多種,這種比較方便)
String text = "測(cè)試inputStream內(nèi)容"; InputStream rawInputStream = new ByteArrayInputStream(text.getBytes()); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len; while ((len = rawInputStream.read(buffer)) > -1) { outputStream.write(buffer, 0, len); } outputStream.flush(); InputStream in1 = new ByteArrayInputStream(outputStream.toByteArray()); InputStream in2 = new ByteArrayInputStream(outputStream.toByteArray()); int readCount1 = in1.read(buffer); int readCount2 = in2.read(buffer); System.out.println("讀取了" + readCount1 + "個(gè)字節(jié)"); System.out.println("讀取了" + readCount2 + "個(gè)字節(jié)"); /** * 執(zhí)行結(jié)果是 * 讀取了23個(gè)字節(jié) * 讀取了23個(gè)字節(jié) *
這里是先將inputStream的數(shù)據(jù)讀取到output中,然后要反復(fù)使用inputStream中的內(nèi)容的時(shí)候,我們將output中的數(shù)據(jù)取出(很神奇的設(shè)定,output可以反復(fù)取,input只能讀一次)
方法二:
其實(shí)inputStream中有操作指針的方法,mark和reset,聽(tīng)名字就知道是標(biāo)記和重置.在使用inputSteam前我們標(biāo)記下inputStream指針的位置,讀取完之后,重置,然后就可以反復(fù)使用了.我們看代碼:
String text = "測(cè)試inputStream內(nèi)容"; InputStream rawInputStream = new ByteArrayInputStream(text.getBytes()); byte[] readArray = new byte[1024]; rawInputStream.mark(0); int readCount1 = rawInputStream.read(readArray); rawInputStream.reset(); int readCount2 = rawInputStream.read(readArray); System.out.println("讀取了" + readCount1 + "個(gè)字節(jié)"); System.out.println("讀取了" + readCount2 + "個(gè)字節(jié)");總結(jié):
1.inputStream只能讀取一次,也就是說(shuō)只能調(diào)用read()或者其他的帶參數(shù)的read()方法一次,在下次調(diào)用讀取出來(lái)是-1,做項(xiàng)目的時(shí)候不要忘記這一點(diǎn)了,可能會(huì)導(dǎo)致有些坑出現(xiàn);
2.可以使用緩存或者mark/reset方法來(lái)重復(fù)使用inputStream,這里要注意的是如果inputStream如果內(nèi)容很多,緩存不是一個(gè)好辦法,因?yàn)樵谑褂猛曛皶?huì)占用大量的內(nèi)存(我遇到過(guò)這樣的,上傳很多圖片然后還有緩存,導(dǎo)致內(nèi)存不夠就一直fullGC,然后cpu先爆了);
3.還有一個(gè)小點(diǎn)就是別忘了關(guān)閉使用完的inputStream/outputSteam.
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/75085.html
摘要:序本文介紹一下如何重復(fù)消費(fèi),普通的,消費(fèi)一次之后,就不能再用了,有時(shí)候需要重復(fù)消費(fèi)的話(huà),就必須自己緩存一下。這里定義了類(lèi),可以用來(lái)實(shí)現(xiàn)這個(gè)目的。開(kāi)啟并重復(fù)使用的時(shí)候一下,然后想重復(fù)使用的時(shí)候一下。 序 本文介紹一下如何重復(fù)消費(fèi)input stream,普通的inputStream,消費(fèi)一次之后,就不能再用了,有時(shí)候需要重復(fù)消費(fèi)的話(huà),就必須自己緩存一下。這里定義了ReuseableStr...
摘要:軟件設(shè)計(jì)原則這篇文章主要討論如何以健壯的方式應(yīng)對(duì)變化的需求,從而保持良好的編程習(xí)慣。前言軟件設(shè)計(jì)是開(kāi)發(fā)周期中最重要的一個(gè)環(huán)節(jié)。識(shí)別出系統(tǒng)會(huì)發(fā)生變化的部分,并將其和不變的部分分開(kāi)。 軟件設(shè)計(jì)原則 這篇文章主要討論如何以健壯的方式應(yīng)對(duì)變化的需求,從而保持良好的編程習(xí)慣。 前言 軟件設(shè)計(jì)是開(kāi)發(fā)周期中最重要的一個(gè)環(huán)節(jié)。在實(shí)現(xiàn)彈性和靈活的設(shè)計(jì)上花的時(shí)間越多,未來(lái)在面對(duì)需求變更時(shí)節(jié)約的時(shí)間就越多。...
摘要:軟件設(shè)計(jì)一直是開(kāi)發(fā)周期中最重要的階段,在設(shè)計(jì)彈性和靈活的體系結(jié)構(gòu)的花費(fèi)的時(shí)間越多,在將來(lái)出現(xiàn)變更時(shí)就越節(jié)省時(shí)間。在本文中,我們將討論有助于創(chuàng)建易于維護(hù)和可擴(kuò)展的軟件的關(guān)鍵設(shè)計(jì)原則。 翻譯: 瘋狂的技術(shù)宅 來(lái)源: Programmer Gate 原文標(biāo)題: Software design principles 英文原文: http://programmergate.com/sof... ...
閱讀 1398·2021-11-17 09:33
閱讀 2002·2021-09-09 11:53
閱讀 3512·2021-09-04 16:45
閱讀 1580·2021-08-17 10:12
閱讀 2577·2019-08-30 15:55
閱讀 1851·2019-08-30 15:53
閱讀 2481·2019-08-30 15:52
閱讀 2642·2019-08-29 18:41