2011-03-01 70 views
1

我正準備在Java中進行編程練習,我希望我的學生能夠發現HTTP本身的內在特性,而不是讓URLConnection爲他們完成所有工作。爲了估計複雜性,我想出了以下片段,它解析了答覆(imho,工作中最難的部分之一),它將返回例如「HTTP/1.1 200 OK」,推之類「服務器:makato」「內容長度:1337」中的矢量,並在內容的第一個字節離開的InputStream,這樣一個DataInputStreamInputStreamReader可以稍後安全地建立在它之上。通過Java套接字接收混合媒體。你更好嗎?

我很想知道是否有更多的Java類經驗的人可以提出更優雅的選擇。我不滿意的一件事是,每個人都是.read()將不可避免地生成一個額外的系統調用(假設Socket.getInputStream()用於餵養參數)。

public static String recvHttpHeaders(InputStream is, Vector<String> headers) 
throws Exception { 
byte line[] = new byte[512]; 
String pending=null; 
String status=null; 
boolean complete=false, CR=false; 
int n=0; 

while (!complete) { 
    int x = is.read(); 
    switch(x) { 
    case -1: throw new Exception("something went wrong"); 
    case '\r': 
      if (CR) throw new Exception("encoding mismatch CRCR"); 
      CR=true; 
      break; 
    case '\n': // bare LF are accepted silently. 
      String ln = new String(line,0,n,"ASCII"); 
      if (pending!=null) ln = pending + ln; 
      if (status==null) status = ln; 
      else headers.add(ln); 
      complete = ln.length()==0; 
      pending = null; 
      n=0; CR=false; 
      break; 
    default: 
      if (CR) throw new Exception("encoding mismatch ?CR"); 
      if (n>=512) { 
       String part = new String(line, "ASCII"); 
       if (pending!=null) pending += part; 
       else pending = part; 
       n=0; 
      } 
      line[n++]=(byte)x; 
      break; 
    } 
} 
return status; 
} 

編輯:誠然,一個喜歡使用xxx.readline()這裏,以避免與線重建搞亂。 BufferedReader(或任何其他* Reader,實際上)根據一個字符集將字節轉換爲字符。這意味着如果我在頭文件解析中使用了該功能,則不再可以自由選擇該內容的字符集。我還沒有找到任何內置readline能力的字節級類。

性能解決方案:感謝您指出BufferedInputStream。我做了一些額外的測試,而事實上,作爲調用

BufferedInputStream bis = new BufferedInputStream(socket.getInputStream()); 
    String status = recvHttpHeaders(bis, headers); 
    rawCopy(bis, output); 

確實減少執行系統調用的數量,還是讓我正確地接收二進制內容不變。

+0

非常高興得到關於_conceiving_作業而不是解決問題的一個問題^^ – Dunaril 2011-03-01 17:07:56

+1

爲了克服系統讀取每讀取問題,您可以通過BufferedInputStream封裝'socket.getInputStream()'。只要你爲標題和正文使用相同的'BufferedInputStream',你就不會有任何問題。 – 2011-03-01 19:06:59

回答

0

繼Sripathi克里希南和亞當潘德,以提高其使用方式的評論一個BufferedInputStream,所以性能仍然可以接受,並且不會發生字符集轉換。

0

您應該使用BufferedReader來讀取文本。包裝你的輸入流:

BufferedReder br = new BufferedReader(new InputStreamReader(is));

然後使用輸入行()來讀取行的東西線:

String line = null; 
while((line = br.readLine()) != null) { 
    // deal with the line 
} 
+1

我希望我可以,但BufferedReader強制你有一個字符集定義(或使用默認字符集)。這意味着我不能再決定以原始字節(用於jpgs和東西)或UTF-8編碼字符(用於xml,html和其他東西)消費HTTP回覆的內容。 – PypeBros 2011-03-01 17:09:21

+1

你只需要使用BufferedInputStream,而不是BufferedReader。流不需要字​​符集,因爲您正在處理原始字節 – 2011-03-01 19:06:06