在Java中流的一系列操做,可能會感到既熟悉又陌生。熟悉是由於很基礎且出鏡率很高,陌生對大多數程序員平時工做中不多寫相關的代碼。java
~~ 我是不多寫~~程序員
迴歸正題,本章我不不是探討流,主要來講下形成‘標題’問題的緣由。數組
問題很簡單,稍微看下源碼或者debug下就能夠找到問題所在,這是一些細節問題,既然出現了在此作下記錄,給本身一個警戒。微信
今天微信上忽然收到前同事一段這樣的問題描述測試
在讀取文件時若是文件爲空、致使進入while死循環,this
並附上一段代碼。debug
/** * 將文件數據流寫入到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; } } } }
咋一看這段代碼也沒啥問題!~是否是~code
咱們一點點的來分析下orm
首先陷入while死循環的條件bInStream.read(buffer)) != -1
ip
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(); }
描述的很清楚,返回此輸入流下一個方法調用能夠不受阻塞地今後輸入流讀取(或跳過)的估計字節數。
說到這基本就反應過來,再說就有點囉嗦了。
像這種問題其實和技術和能力沒多大關係、主要是細心和經驗。其實定義一個程序員的牛逼與否在於他踩過的坑是否足夠多。
既然說到這那就順便溫故下InputStream的幾個方法吧!
int available() : 返回此輸入流下一個方法調用能夠不受阻塞地今後輸入流讀取(或跳過)的估計字節數。void close() : 關閉此輸入流並釋放與該流關聯的全部系統資源。
void mark(int readlimit): 在此輸入流中標記當前的位置。
boolean markSupported() : 測試此輸入流是否支持 mark 和 reset 方法。
abstract int read() : 測試此輸入流是否支持 mark 和 reset 方法。
int read(byte[] b) : 從輸入流中讀取必定數量的字節,並將其存儲在緩衝區數組 b 中。
int read(byte[] b, int off, int len) : 將輸入流中最多 len 個數據字節讀入 byte 數組。
void reset() : 將此流從新定位到最後一次對此輸入流調用 mark 方法時的位置。
long skip(long n) : 跳過和丟棄此輸入流中數據的 n 個字節。
以次簡單的問題來對InputStream 溫故。
若有分析的錯誤的地方、歡迎指正