摘要:引語之前做項目的時候遇到一個問題就是從網絡中讀取的圖片要上傳到而且要對圖片進行裁剪和壓縮其中上傳和裁剪都要使用到圖片的又因為不能重復讀導致裁剪是成功的而上傳是失敗的我們今天就提供兩種方法來解決不能重復讀的問題問題分析的內部有個指針當讀取的時
引語:
????之前做項目的時候遇到一個問題,就是從網絡中讀取的圖片要上傳到oss,而且要對圖片進行裁剪和壓縮,其中上傳和裁剪都要使用到圖片的inputStream,
又因為inputstream不能重復讀,導致裁剪是成功的,而上傳是失敗的.我們今天就提供兩種方法來解決,inputStream不能重復讀的問題.
inputStream的內部有個pos指針,當讀取的時候指針會不斷的移動,當移動到末尾的時候,就無法再次讀取了.
我們寫個簡單的例子來看下:
String text = "測試inputStream內容"; InputStream inputStream = new ByteArrayInputStream(text.getBytes()); byte[] readArray = new byte[inputStream.available()]; int readCount1 = inputStream.read(readArray); System.out.println("讀取了" + readCount1 + "個字節"); byte[] readArray2 = new byte[inputStream.available()]; int readCount2 = inputStream.read(readArray2); System.out.println("讀取了" + readCount2 + "個字節"); /** * 執行結果是 * 讀取了23個字節 * 讀取了-1個字節 */
從執行結果可以看出確實inputstream的設計是只能讀取一次.
注意: 這里稍微提一下inputStream.available()這個方法,本地的文件可以直接知道文件的大小,但是如果是網絡中的數據,這個方法最好不要用,因為傳輸的時候不是連續的,數據的大小會讀取不準
那么我們實際項目中應該怎么解決呢?總不能就真的只使用一次inputSteam吧.我們來看解決方法:
方法一:
使用ByteArrayOutputStream來緩存字節,然后每次讀取從緩存的ByteArrayOutputStream中拿取.
很自然的想到把inputStream的緩存起來(當然不一定說是要放在ByteArrayOutputStream,其他的方式也可以,都是緩存起來的思路,實現方式有很多種,這種比較方便)
String text = "測試inputStream內容"; 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 + "個字節"); System.out.println("讀取了" + readCount2 + "個字節"); /** * 執行結果是 * 讀取了23個字節 * 讀取了23個字節 *
這里是先將inputStream的數據讀取到output中,然后要反復使用inputStream中的內容的時候,我們將output中的數據取出(很神奇的設定,output可以反復取,input只能讀一次)
方法二:
其實inputStream中有操作指針的方法,mark和reset,聽名字就知道是標記和重置.在使用inputSteam前我們標記下inputStream指針的位置,讀取完之后,重置,然后就可以反復使用了.我們看代碼:
String text = "測試inputStream內容"; 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 + "個字節"); System.out.println("讀取了" + readCount2 + "個字節");總結:
1.inputStream只能讀取一次,也就是說只能調用read()或者其他的帶參數的read()方法一次,在下次調用讀取出來是-1,做項目的時候不要忘記這一點了,可能會導致有些坑出現;
2.可以使用緩存或者mark/reset方法來重復使用inputStream,這里要注意的是如果inputStream如果內容很多,緩存不是一個好辦法,因為在使用完之前會占用大量的內存(我遇到過這樣的,上傳很多圖片然后還有緩存,導致內存不夠就一直fullGC,然后cpu先爆了);
3.還有一個小點就是別忘了關閉使用完的inputStream/outputSteam.
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/75085.html
摘要:序本文介紹一下如何重復消費,普通的,消費一次之后,就不能再用了,有時候需要重復消費的話,就必須自己緩存一下。這里定義了類,可以用來實現這個目的。開啟并重復使用的時候一下,然后想重復使用的時候一下。 序 本文介紹一下如何重復消費input stream,普通的inputStream,消費一次之后,就不能再用了,有時候需要重復消費的話,就必須自己緩存一下。這里定義了ReuseableStr...
摘要:軟件設計原則這篇文章主要討論如何以健壯的方式應對變化的需求,從而保持良好的編程習慣。前言軟件設計是開發周期中最重要的一個環節。識別出系統會發生變化的部分,并將其和不變的部分分開。 軟件設計原則 這篇文章主要討論如何以健壯的方式應對變化的需求,從而保持良好的編程習慣。 前言 軟件設計是開發周期中最重要的一個環節。在實現彈性和靈活的設計上花的時間越多,未來在面對需求變更時節約的時間就越多。...
閱讀 1274·2021-11-17 09:33
閱讀 1742·2021-09-09 11:53
閱讀 3208·2021-09-04 16:45
閱讀 1382·2021-08-17 10:12
閱讀 2383·2019-08-30 15:55
閱讀 1779·2019-08-30 15:53
閱讀 2404·2019-08-30 15:52
閱讀 2558·2019-08-29 18:41