透過InputStreamReader讀取InputStream可能會失敗


Java的I/O函式庫可分成讀寫字節流的InputStream和OutputStream和讀寫字元流的Reader和Writer。如果InputStream的內容都是字元,那麼可以透過InputStreamReader,將InputStream轉為Reader。通常使用Reader讀取文字會比使用InputStream讀取還要來得方便,因為InputStream是以byte為單位,而Reader是以char為單位。但是最近筆者發現InputStreamReader(或是Reader本身)有一些問題,呼籲大家最好不要再使用InputStreamReader(或是Reader)了。

發生過程

事情是這樣的發生的,筆者在Android上使用InputStreamReader來讀取URLConnection的InputStream(getInputStream()),因為確定該URL會回傳純文字的內容,所以很直覺的就使用Reader來處理文字。但是,後來卻發現InputStreamReader在某些Android 4.3版本以下的裝置(不是所有裝置)上,讀取特定的InputStream內容時,會沒辦法正常的讀取,InputStreamReader的ready()方法永遠傳回false,但是InputStream內卻是有資料的。

推測原因

單就問題的發生過程來看,Android 4.3版本以下某些裝置上的Java Runtime環境可能有BUG,會導致特定資料內容的InputStream無法使用InputStreamReader進行讀取。

最遭的情況是,任意平台下的Java Runtime環境可能都有這個BUG,會導致特定資料無法使用Reader來讀取。

處理方式

將InputStream讀取到ByteArrayOutputStream中,而不使用InputStreamReader。然後再將ByteArrayOutputStream讀出來的byte陣列(toByteArray())解碼(decode)成原本的文字(String)。之後再進行測試,結果完全正常。

結論

若要避免掉這問題的發生,那就別再使用InputStreamReader了!要更保險一點的話,連Reader也不要用了。

一般使用Reader來讀取InputStream的文字,可能會撰寫以下程式:

若配合BufferedReader,程式會較容易理解:

不使用Reader的話,可以改用ByteArrayOutputStream來暫存byte陣列,之後再用new String的方式進行byte陣列的文字解碼,程式如下:

用以上的方式來讀取文字,因為沒有使用到Reader,所以也就沒有讀取失敗的問題了。

關於作者

Magic Len

各位好,我是Magic Len,是這網站的管理員。我是台灣台中大肚山上人,畢業於台中高工資訊科和台灣科技大學資訊工程系,曾在桃機航警局服役。我熱愛自然也熱愛科學,喜歡和別人分享自己的知識與經驗。如果你有興趣認識我,可以加我的Facebook,並且請註明是從MagicLen來的。

相關文章