深入理解read(byte[] b)與readFully(byte[] b)

要搞清楚read(byte[] b)和readFully(byte[] b)的區別,可以從以下方面着手分析:

1.代碼的具體實現

2.方法何時返回

3.字節是以什麼方式在網絡上傳輸的


1.read(byte[] b)調用read(byte[] b,0,b.length),其中的部分關鍵代碼如下

 

  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;
 

readFully(byte[] b)調用readFully(byte[] b,0,b.length),其中的部分關鍵代碼如下

 

       int n = 0;
        while (n < len) {//該方法一直阻塞,直到讀取到字節數據緩衝區裝滿
            int count = in.read(b, off + n, len - n);
            if (count < 0)
                throw new EOFException();
            n += count;
        }

       //read(bytes[] b,int off,int len)中的關鍵代碼
       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;
 

 


2.從以上代碼,我們可以看到,read(byte[] b)一直阻塞等待讀取字節,直到字節流中的數據已經全部讀完。而readFully(byte[] b)是當數據緩衝區的空間還有剩餘時會阻塞等待讀取,直到裝滿。


3.下圖反映了字節流數據是如何通過網絡的

TCP報文傳送圖

應用程序用輸出流將數據輸入TCP的發送緩存中,這些數據被分割成TCP認爲最適合發送的數據塊(報文段或段)。報文段通過網絡的傳輸到達指定地址(URL)的TCP接收緩存中,接收到的報文段很有可能不是順序到達的,但TCP可以根據報文段的序號進行排序並存儲在TCP接收緩存中。應用程序如果需要獲得這些數據,需要通過輸入流讀取並解析這些報文段。



通過分析以上三個問題,我們可以解釋以下代碼存在的問題:

 

//發送端:
OutputStream out = ......;//通過TCP連接得到輸出流對象
String content = "...";
byte[] data = content.getBytes();
output.write(data);
int len = data.length;
while (len++ < 30) {
	output.writeByte('\0');//補夠30個字節
}
//接收端:	
InputStream in = ......;//通過TCP連接得到輸入流對象
byte[] bytes = new byte[30];
in.read(bytes);
 

由於字節數據是在網絡中通過TCP連接進行傳輸,這些數據剛剛到達接收端(存儲在TCP接收緩衝區)的可能只是其中的一部分數據,其他的數據可能還在傳輸中甚至在發送端的TCP緩存中。在調用read(byte[] b)讀取數據時,b中得到的就是發出的30個字節的一部分。

要想完全獲得這30個字節數據,合理的方法是用readFully(byte[] b)讀取,因爲該方法會一直阻塞等待,直到30個數據全部到達(數據緩衝區裝滿)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章