踩坑筆記 >> InputStream.read(byte[]) 造成死循環(huán)

寫在前面


在Java中流的一系列操作对湃,可能會感到既熟悉又陌生询吴。熟悉是因為很基礎且出鏡率很高杯矩,陌生對大多數程序員平時工作中很少寫相關的代碼。

~~ 我是很少寫~~

回歸正題巾表,本章我不不是探討流汁掠,主要來說下造成‘標題’問題的原因。

問題很簡單集币,稍微看下源碼或者debug下就可以找到問題所在考阱,這是一些細節(jié)問題,既然出現了在此做下記錄鞠苟,給自己一個警惕乞榨。

場景引入


今天微信上突然收到前同事一段這樣的問題描述

在讀取文件時如果文件為空、導致進入while死循環(huán)当娱,

并附上一段代碼吃既。

/**
     * 將文件數據流寫入到zip流中
     * 
     * @param fileName
     * @param inputStream
     * @param outputStream
     * @throws IOException
     */
    public static void zipInputStream(String fileName, InputStream inputStream, ZipOutputStream outputStream)
            throws IOException {
        try {
            BufferedInputStream bInStream = new BufferedInputStream(inputStream);
            outputStream.putNextEntry(new ZipEntry(fileName));
            byte[] buffer = new byte[inputStream.available()];
            int r = 0;
            while ((r = bInStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, r);
            }
            outputStream.closeEntry();
        } catch (IOException e) {
            throw e;
        } finally {
            if (null != inputStream) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    throw e;
                }
            }
        }
    }

咋一看這段代碼也沒啥問題!

我們一點點的來分析下

首先陷入while死循環(huán)的條件bInStream.read(buffer)) != -1

while ((r = bInStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, r);
}

看下源碼中的描述跨细,

/**
     * Reads up to <code>len</code> bytes of data from this input stream
     * into an array of bytes. If <code>len</code> is not zero, the method
     * blocks until some input is available; otherwise, no
     * bytes are read and <code>0</code> is returned.
     * <p>
     * This method simply performs <code>in.read(b, off, len)</code>
     * and returns the result.
     *
     * @param      b     the buffer into which the data is read.
     * @param      off   the start offset in the destination array <code>b</code>
     * @param      len   the maximum number of bytes read.
     * @return     the total number of bytes read into the buffer, or
     *             <code>-1</code> if there is no more data because the end of
     *             the stream has been reached.
     * @exception  NullPointerException If <code>b</code> is <code>null</code>.
     * @exception  IndexOutOfBoundsException If <code>off</code> is negative,
     * <code>len</code> is negative, or <code>len</code> is greater than
     * <code>b.length - off</code>
     * @exception  IOException  if an I/O error occurs.
     * @see        java.io.FilterInputStream#in
     */
    public int read(byte b[], int off, int len) throws IOException {
        return in.read(b, off, len);
    }

上面描述有這么一段鹦倚,如果byte[]數組的len為0則不做任何操作直接返回0。

看到這問題基本就可以定位了冀惭,在看代碼中byte[]的定義震叙。

byte[] buffer = new byte[inputStream.available()];

看到這小伙們就笑了inputStream.available()掀鹅,你讀的是一個空文件可不是為0。

/**
     * Returns an estimate of the number of bytes that can be read (or
     * skipped over) from this input stream without blocking by the next
     * caller of a method for this input stream. The next caller might be
     * the same thread or another thread.  A single read or skip of this
     * many bytes will not block, but may read or skip fewer bytes.
     * <p>
     * This method returns the result of {@link #in in}.available().
     *
     * @return     an estimate of the number of bytes that can be read (or skipped
     *             over) from this input stream without blocking.
     * @exception  IOException  if an I/O error occurs.
     */
    public int available() throws IOException {
        return in.available();
    }

描述的很清楚媒楼,返回此輸入流下一個方法調用可以不受阻塞地從此輸入流讀壤肿稹(或跳過)的估計字節(jié)數。

說到這基本就反應過來匣砖,再說就有點啰嗦了科吭。

總結


像這種問題其實和技術和能力沒多大關系、主要是細心和經驗猴鲫。其實定義一個程序員的牛逼與否在于他踩過的坑是否足夠多。

既然說到這那就順便溫故下InputStream的幾個方法吧谣殊!

方法摘要

int available() : 返回此輸入流下一個方法調用可以不受阻塞地從此輸入流讀确鞴病(或跳過)的估計字節(jié)數。

void close() : 關閉此輸入流并釋放與該流關聯的所有系統(tǒng)資源姻几。

void mark(int readlimit): 在此輸入流中標記當前的位置宜狐。

boolean markSupported() : 測試此輸入流是否支持 mark 和 reset 方法。

abstract int read() : 測試此輸入流是否支持 mark 和 reset 方法蛇捌。

int read(byte[] b) : 從輸入流中讀取一定數量的字節(jié)抚恒,并將其存儲在緩沖區(qū)數組 b 中。

int read(byte[] b, int off, int len) : 將輸入流中最多 len 個數據字節(jié)讀入 byte 數組络拌。

void reset() : 將此流重新定位到最后一次對此輸入流調用 mark 方法時的位置俭驮。

long skip(long n) : 跳過和丟棄此輸入流中數據的 n 個字節(jié)。

以次簡單的問題來對InputStream 溫故春贸。

如有分析的錯誤的地方混萝、歡迎指正

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市萍恕,隨后出現的幾起案子逸嘀,更是在濱河造成了極大的恐慌,老刑警劉巖允粤,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件崭倘,死亡現場離奇詭異,居然都是意外死亡类垫,警方通過查閱死者的電腦和手機司光,發(fā)現死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來阔挠,“玉大人飘庄,你說我怎么就攤上這事」汉常” “怎么了跪削?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵谴仙,是天一觀的道長。 經常有香客問我碾盐,道長晃跺,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任毫玖,我火速辦了婚禮掀虎,結果婚禮上,老公的妹妹穿的比我還像新娘付枫。我一直安慰自己烹玉,他們只是感情好,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布阐滩。 她就那樣靜靜地躺著二打,像睡著了一般。 火紅的嫁衣襯著肌膚如雪掂榔。 梳的紋絲不亂的頭發(fā)上继效,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天,我揣著相機與錄音装获,去河邊找鬼瑞信。 笑死,一個胖子當著我的面吹牛穴豫,可吹牛的內容都是我干的凡简。 我是一名探鬼主播,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼绩郎,長吁一口氣:“原來是場噩夢啊……” “哼潘鲫!你這毒婦竟也來了?” 一聲冷哼從身側響起肋杖,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤溉仑,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后状植,有當地人在樹林里發(fā)現了一具尸體浊竟,經...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年津畸,在試婚紗的時候發(fā)現自己被綠了振定。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡肉拓,死狀恐怖后频,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤卑惜,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布膏执,位于F島的核電站,受9級特大地震影響露久,放射性物質發(fā)生泄漏更米。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一毫痕、第九天 我趴在偏房一處隱蔽的房頂上張望征峦。 院中可真熱鬧,春花似錦消请、人聲如沸栏笆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽竖伯。三九已至,卻和暖如春因宇,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背祟偷。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工察滑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人修肠。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓贺辰,卻偏偏與公主長得像,于是被迫代替她去往敵國和親嵌施。 傳聞我的和親對象是個殘疾皇子饲化,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內容

  • 前提 參考資料: 《Java I/O》 -- 這本書沒有翻譯版,需要自己啃一下吗伤。 《Java I/O》這本書主要介...
    zhrowable閱讀 1,175評論 0 1
  • tags:io categories:總結 date: 2017-03-28 22:49:50 不僅僅在JAVA領...
    行徑行閱讀 2,178評論 0 3
  • 1.java IO流的概念吃靠,分類,類圖 1.1. java IO 流的概念 java的io是實現輸入和輸出的基礎足淆,...
    onlyHalfSoul閱讀 576評論 0 1
  • Java輸入輸出流(一)# Android 是基于 Java 語言編寫的巢块,在安卓程序的很多時候會用到有關 I/O ...
    梁加鹽閱讀 1,411評論 0 4
  • 一、基礎知識:1巧号、JVM族奢、JRE和JDK的區(qū)別:JVM(Java Virtual Machine):java虛擬機...
    殺小賊閱讀 2,383評論 0 4