2010-11-07 78 views
3

我試圖連接到服務器,然後發送一個HTTP請求(在這種情況下爲GET)。這個想法是請求一個文件,然後從服務器接收它。從套接字讀取二進制數據

它應該同時處理文本文件和二進制文件(例如imgs)。我對文本文件沒有問題,它的工作原理非常完美,但是我在使用二進制文件時遇到了一些麻煩。

首先,我聲明一個BufferedReader(讀頭和文本文件)和DataInput中的流:

BufferedReader in_text = new BufferedReader(
    new InputStreamReader(socket.getInputStream())); 

DataInputStream in_binary = new DataInputStream(
    new BufferedInputStream(socket.getInputStream())); 

然後,我閱讀in_text頭,發現如果它是一個文本文件或二進制文件。如果它是一個文本文件,我在StringBuilder中正確讀取它。如果是二進制文件,我聲明一個字節[filesize]並存儲in_binary的以下內容。

byte[] bindata = new byte[filesize]; 
in_binary.readFully(bindata); 

而且它不起作用。我得到一個EOFException。

我以爲可能in_binary仍然在流的第一個位置,所以它還沒有讀取頭。所以我捕獲了頭部的長度並在in_binary中跳過了這些字節。

byte[] bindata = new byte[filesize]; 
in_binary.reset(); 
in_binary.skip(headersize); 
in_binary.readFully(bindata); 

而且依然如此。

會發生什麼情況?

謝謝!

PD:我知道我可以使用URLConnection和所有這些。這不是問題。

回答

3

BufferedReader緩衝數據(因此名稱) - 它幾乎肯定會從套接字讀取更多的數據而不僅僅是頭部。因此,當您嘗試讀取某些已經從套接字讀取的實際數據時。如果您嘗試讀取幾個字節,您可能會發現它們不是實際響應數據的第一個字節。

如果你知道如何使用URLConnection,我不知道你有什麼理由不使用它。

+0

啊!我認爲這是重點。我將嘗試使用InputStream來讀取頭文件。還是有另一個更好的解決方案?我只是想了解HTTP如何工作,這不適用於任何「專業」使用,這就是爲什麼我不使用URLConnection;) – 2010-11-07 16:04:05

+0

我會做以下事情:首先,我會從流和緩衝區讀取,直到我請參閱HTTP響應標頭的末尾(「\ r \ n \ r \ n」)。這將是響應標題。您可以使用ASCII編碼將其解碼爲字符串,然後解析它以獲取內容長度。然後,發出另一個讀取內容長度字節的流。 – feroze 2010-11-07 17:59:20

1

只要您使用Reader的任何子類,就不會讀取二進制文件。您正在使用JVM的默認編碼將字節轉換爲字符。如果你真的想要二進制字節,你需要堅持流,而不是讀者。同時創建兩個堆棧正在尋求麻煩。

使用Apache Commons IO:IOUtils.toByteArray()將整個內容作爲byte []讀入內存,然後決定如何處理它,除非您擁有大量的數據,在這種情況下您應該設置緩衝的輸入流,決定要做什麼,並且只有在推回後才構建讀取器。

+0

我只使用BufferedReader作爲頭文件和HTML文件,而不是二進制數據。 – 2010-11-07 16:05:44