通過閱讀InputStream類和FileInputStream類裏的read()方法(native方法)的源碼,read()方法的返回值有兩種含義,雖然他們都是int類型。下面我們來看一下源碼:
/**
* Reads the next byte of data from the input stream. The value byte is
* returned as an <code>int</code> in the range <code>0</code> to
* <code>255</code>. If no byte is available because the end of the stream
* has been reached, the value <code>-1</code> is returned. This method
* blocks until input data is available, the end of the stream is detected,
* or an exception is thrown.
*
* <p> A subclass must provide an implementation of this method.
*
* @return the next byte of data, or <code>-1</code> if the end of the
* stream is reached.
* @exception IOException if an I/O error occurs.
*/
public abstract int read() throws IOException;
這個無參的read()方法返回的int類型,是表示數據下一個字節的字節碼,如果已經到達流的最後面了,那就返回-1.
public int read(byte b[], int off, int len) throws IOException {
//這裏是一些前期判斷,我們的buffer[]數組不能爲空,偏移量一開始不能比0小,要讀取的字節長度也不能比0小
if (b == null) {
throw new NullPointerException();
} else if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
int c = read();
if (c == -1) {
return -1;
}
b[off] = (byte)c;
int i = 1;
try {
for (; i < len ; i++) {
c = read();
if (c == -1) {
break;
}
b[off + i] = (byte)c;
}
} catch (IOException ee) {
}
return i;
}
//--------------------分割線--------------------------
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);
}
兩個帶參數read()方法返回的是讀取的字節數。(到達流數據的末端返回值爲-1,這個是共同點,下面不再討論)
read(byte b[])方法實際上是調用了 read(byte b[], int off, int len)方法,它的返回值的大小取決於兩方面。假如當流數據的字節數小於我們給定的buffer[]數組長度的話,那麼這個返回值,就應該是流數據的字節長度。當流數據的總字節長度大於我們的buffer[]數組長度的話,那麼這個返回值就是我們的數字長度了。因爲read方法的是用一個for循環來將讀到的每個字節存到我們設定的buffer[]數組中的,當i=len的時候,就跳出循環,返回i。(所以這裏也應該說明了,read()方法應該有個指針指到了本次讀取的最後一個字節碼,並且保持位置,直到當我們下一次使用read()方法來訪問這個文件輸入流對象,再重新在這個地方開始讀取字節碼,這樣才能保證我們能夠把整個文件完整地讀完)
public int read(byte b[], int off, int len)方法的返回值就是我們設定的要讀取的字節碼的長度,或者是從偏移量off處開始到流數據末端的字節數了。
知道了read()方法的工作原理之後,我們再來看我們的問題,爲什麼無參的read()方法的返回值是int類型而不是byte。總所周知,Java中的數字都是有符號數,假如我們用一個byte類型去接收流中的字節碼的話,那麼假如剛好字節流裏的字節碼是-1的反碼,那這個時候,read()返回了一個-1,那我們怎麼知道read()是到達了流的末端還是字節碼就是-1呢。而假如我們使用int類型的c來接收這些字節碼,就不會出現這樣的問題,高位補零,接收到的字節碼放在最低的八位上,這樣就能保證這些字節碼都是“正數”。