2012-09-18 56 views
4

我通過HttpURLConnection向服務器發出一個http獲取請求,我需要兩次讀取響應(InputStream):用於記錄目的和解析響應。返回的InputStraemorg.apache.harmony.luni.internal.net.www.protocol.http.ChunkedInputStream的實例,不支持標記(is.markSupported()返回false)。HttpURLConnection讀取InputStream兩次

因此我不能mark()reset()流,並在日誌中寫入響應後我無法解析它。當然,我可以在String或其他地方讀取響應一次,記錄它們並稍後解析。但是當我使用流時,我會避免潛在的OutOfMemomryError,因爲流處理緩衝而不是我。

在這種情況下,什麼是最好的解決方案,它將保持使用流的好處並幫助達到預期的結果:同時記錄到日誌和解析響應中?

編輯:解決方案與寫作響應到臨時文件是不恰當的

回答

4

我不確定我完全理解,你想讀一次InputStream(不是真的兩次,這有點不潔IMO,因爲如果錯誤只發生在日誌流而不是你正在解析的流?),然後簡單地記錄和解析相同的InputStream

如果以上是在這裏展示的解決方案的情況下,僞:

InputStream is=...; 
byte[] bytes=new byte[1028]; 
while(is.read(bytes)!=-1) { 
log(bytes); //call function to log 
parse(bytes);//call function to parse 
} 

即使同時進行記錄和記錄更好的將是創造兩種方法的新Thread/Runnable,開始他們恨不得返回使用(thread.join();):

InputStream is=...; 
byte[] bytes=new byte[1028]; 
while(is.read(bytes)!=-1) { 
Thread t1=new Thread(new Runnable() { 
     @Override 
     public void run() { 
      log(bytes); //call function to log 
     } 
    }); 
Thread t2=new Thread(new Runnable() { 
     @Override 
     public void run() { 
      parse(bytes);//call function to parse 
     } 
    }); 
    t1.start(); 
    t2.start(); 
try { 
    t1.join(); 
    t2.join(); 
    }catch(Exception ex) { 
     ex.printStackTrace(); 
    } 
} 
+0

我想兩次訪問完整的流內容(內容是JSON格式的字符串):第一個 - 只是寫在日誌中,第二個 - 解析反應 –

+1

無論哪種方式,一旦你有JSON格式的字符串傳遞給*解碼*的方法,然後將返回的'String'傳遞給'log()'和'parse()'。一個Stream是我提到的兩次,另一個回答 –

+0

代碼有缺陷,它忽略了'read()'的結果,所以它很容易在每個緩衝區結束時處理垃圾。 – EJP

0

如果你事先不知道流的潛在規模(或者如果它是太大而不能放在一個String或一個byte[]),然後我會使用HttpURLConnectionInputStream進行記錄(如果需要,可能在一個單獨的文件中),我會使用日誌文件進行解析。

這可能不是複製InputStream的最有效方式,但可能是最安全的記憶之一。

+0

感謝您的回答,但是這個解決方案太慢並且體積太大( –

2

你不應該需要讀取的輸入流的兩倍。在閱讀時記錄它。