1. 程式人生 > >Java InputStream讀取網路響應Response資料的方法!(重要)

Java InputStream讀取網路響應Response資料的方法!(重要)

Java InputStream讀取資料問題

======================================================================

原理講解 


1. 關於InputStream.read()
     在從資料流裡讀取資料時,為圖簡單,經常用InputStream.read()方法。這個方法是從流裡每次只讀取讀取一個位元組,效率會非常低。     更好的方法是用InputStream.read(byte[] b)或者InputStream.read(byte[] b,int off,int len)方法,一次讀取多個位元組。
 

2. 關於InputStream類的available()方法
    要一次讀取多個位元組時,經常用到InputStream.available()方法,這個方法可以在讀寫操作前先得知資料流裡有多少個位元組可以讀取。需要注意的是,如果這個方法用在從本
地檔案讀取資料時,一般不會遇到問題,但如果是用於網路操作,就經常會遇到一些麻煩。比如,Socket通訊時,對方明明發來了1000個位元組,但是自己的程式呼叫available()方法卻只得到900,或者100,甚至是0,感覺有點莫名其妙,怎麼也找不到原因。其實,這是因為網路通訊往往是間斷性的,一串位元組往往分幾批進行傳送。本地程式呼叫available()方法有時得到0,這可能是對方還沒有響應,也可能是對方已經響應了,但是資料還沒有送達本地。對方傳送了1000個位元組給你,也許分成3批到達,這你就要呼叫3次available()方法才能將資料總數全部得到。

      如果這樣寫程式碼:

int count = in.available();  
  byte[] b = new byte[count];  
  in.read(b);
在進行網路操作時往往出錯,因為你呼叫available()方法時,對發發送的資料可能還沒有到達,你得到的count是0。
         需要改成這樣:
int count = 0;  
 while (count == 0) {  
  //count = in.available();  
  
  count=response.getEntity().getContentLength();//(HttpResponse response)  
 }  
 byte[] b = new byte[count];  
 in.read(b); 

3. 關於InputStream.read(byte[] b)和InputStream.read(byte[] b,int off,int len)這兩個方法都是用來從流裡讀取多個位元組的,有經驗的程式設計師就會發現,這兩個方法經常 讀取不到自己想要讀取的個數的位元組。比如第一個方法,程式設計師往往希望程式能讀取到b.length個位元組,而實際情況是,系統往往讀取不了這麼多。仔細閱讀Java的API說明就發現了,這個方法 並不保證能讀取這麼多個位元組,它只能保證最多讀取這麼多個位元組(最少1個)。因此,如果要讓程式讀取count個位元組,最好用以下程式碼:
  byte[] bytes = new byte[count];  
  int readCount = 0; // 已經成功讀取的位元組的個數  
  while (readCount < count) {  
   readCount += in.read(bytes, readCount, count - readCount);  
  }

用這段程式碼可以保證讀取count個位元組,除非中途遇到IO異常或者到了資料流的結尾(EOFException).

==========================================================================================

程式碼分享

下面分享我自己寫的測試程式碼片段,供大家參考:

    /** 
         * <b>獲取指定的URL返回的資料資訊</b> 
         * @param <font color="#efac10"><a href="http://www.baidu.com">_url:指定的URL</a></font> 
         * @return 
         * @throws ClientProtocolException 
         * @throws IOException 
         */  
        public String getReponse(String _url) throws ClientProtocolException, IOException  
        {  
            String readContent=null;  
            DefaultHttpClient httpclient = new DefaultHttpClient();  
            HttpGet httpget = new HttpGet(SinaJsonTest.SinaUrl);  
            System.out.println("0.Send the URL to Sina Sever....");  
            HttpResponse response = httpclient.execute(httpget);  
            HttpEntity entity = response.getEntity();  
      
            System.out.println("1.Get Response Status: " + response.getStatusLine());  
            if (entity != null) {  
                System.out.println("  Get ResponseContentEncoding():"+entity.getContentEncoding());  
                System.out.println("  Content Length():"+entity.getContentLength());  
                //getResponse  
                InputStream in=entity.getContent();  
                int count = 0;  
                while (count == 0) {  
                 count = Integer.parseInt(""+entity.getContentLength());//in.available();  
                }  
                byte[] bytes = new byte[count];  
                int readCount = 0; // 已經成功讀取的位元組的個數  
                while (readCount <= count) {  
                 if(readCount == count)break;  
                 readCount += in.read(bytes, readCount, count - readCount);  
                }  
                  
                //轉換成字串  
                readContent= new String(bytes, 0, readCount, "UTF-8"); // convert to string using bytes  
      
                System.out.println("2.Get Response Content():\n"+readContent);  
            }  
            return readContent;  
        }  

轉載自:http://blog.csdn.net/hurryjiang/article/details/6688247