2014-09-16 2 views
2

Я знаю, что это было задано раньше, но поскольку я не смог найти ответ с окончательным заключением или, по крайней мере, одним из них, который показывает плюсы и минусы возможных подходов, я должен спросить:HttpURLConnection: Каков правильный способ чтения данных из WebService, символа или символа или строки за строкой?

Когда дело доходит до чтения данных из Интернета, например, веб-службы, какой правильный или более эффективный способ читать эти данные?

Из всех книг, которые я бросил взгляд, я нашел, по крайней мере 4 способа считывания данных:

1) Чтение определенного количества символов в то время. В этом случае данные считываются на куски из 4026 символов

BufferedReader reader = new BufferedReader(
new InputStreamReader(in, encoding)); 
char[] buffer = new char[4096]; 
StringBuilder sb = new StringBuilder(); 
int downloadedBytes = 0; 
int len1 = 0; 
while ((len1 = reader.read(buffer)) > 0) { 
    sb.append(buffer); 
} 
return sb.toString(); 

2) Считывание данных зная контента длины

int length =(HttpURLConnection) urlConnection.getContentLength(); 
InputStream inputStream = urlConnection.getInputStream(); 
BufferedReader bufferedReader =new BufferedReader(new InputStreamReader(inputStream)); 
StringBuilder stringBuilder = new StringBuilder(length); 
char[] buffer = new char[length]; 
int charsRead; 
while ((charsRead = bufferedReader.read(buffer)) != -1) { 
    stringBuilder.append(buffer, 0, charsRead); 
} 
return stringBuilder.toString(); 

3) Считать линию передачи данных по линии:

BufferedReader reader=new BufferedReader(new InputStreamReader(c.getInputStream())); 
StringBuilder buf=new StringBuilder(); 
String line=null; 
while ((line=reader.readLine()) != null) { 
    buf.append(line); 
} 
return(buf.toString()); 

4) Прочитать данные по символам:

InputStream in = mConnection.getInputStream(); 
BufferedReader reader = new BufferedReader(new InputStreamReader(
     in, enconding));  
int ch; 
StringBuilder sb = new StringBuilder();   
while ((ch=reader.read()) > 0) {    
    sb.append((char)ch); 
} 

return sb.toString().trim(); 

Я пробовал 3 из этих 4 разных методов, за исключением номера 3 (читай данные по строкам), и из трех методов только четвертый дал мне хорошие результаты.

  • Первый метод не работает для меня, потому что, когда я прочитал большое количество данных, как это часто вырезать данные, дающие мне в результате некорректных строк JSON или строку с пробелами в конце.
  • Второй подход, ну, я не смог использовать этот метод, потому что getContentLength не всегда надежный, и если значение не задано, мы ничего не можем с этим поделать, ну это мой случай.
  • Я не пробовал третий метод, потому что я не был уверен в том, что «строка» считывает данные «линия». Это относится к данным, содержащим массив json-объектов или только к файлам, которые действительно содержат строки?
  • Будучи последней техникой последнего выбора, с которым я остался, я попробовал, и это сработало, НО Я не думаю, что чтение большого количества символов данных по характеру было бы эффективным вообще.

Так что теперь я был бы очень признателен за ваши мнения и идеи. Какой подход вы используете, когда дело доходит до чтения данных из веб-служб? и что еще более важно, почему?

Спасибо.

P.D. Я знаю, что мог бы легко использовать DefaultHttpClient, но the doc явно не рекомендует этого делать.

Для Android 2.3 (Gingerbread), а позже HttpURLConnection - лучший выбор . Его простой API и небольшие размеры делают его очень подходящим для Android. Прозрачное сжатие и ответное кэширование уменьшают использование сети, улучшают скорость и экономят аккумулятор.

ответ

2

Ive пробовал все методы, о которых вы упоминали. Одна из проблем заключалась в том, что ответ был полностью не прочитан. После некоторых исследований, наиболее эффективный/быстрый способ я нашел в том, чтобы идти об этом, как этот

 DefaultHttpClient client = new DefaultHttpClient(); 
       HttpGet httpGet = new HttpGet(url); 

       httpGet.setHeader("Accept", "application/json"); 
       httpGet.setHeader("Content-type", "application/json"); 
//ive put json header because im using json 


       try { 
        HttpResponse execute = client.execute(httpGet); 


        String responseStr = EntityUtils.toString(execute.getEntity()); 

       } 

responseStr будет содержать WebService ответ, и он читает его на одном дыхании. Надеюсь, это поможет

+2

Спасибо @ZInj за то, что нашли время ответить. Я знаю, что DefaultHttpClient предоставляет более простой способ чтения/записи данных, но официальный документ говорит следующее: «Для Android 2.3 (Gingerbread), а позже HttpURLConnection - лучший выбор. Его простой API и небольшие размеры делают его очень подходящим для Android. Прозрачное сжатие и ответное кэширование уменьшают использование сети, улучшают скорость и экономят батарею. Http://goo.gl/4zyIki – eddy

2

Если объем данных не слишком велик, это не имеет большого значения, какой подход вы используете. Если это так, тогда имеет смысл использовать буферизацию - и читать данные в кусках.

2-й подход не слишком хорош, так как вы не всегда можете получить ContentLength.

Тогда, если ваши данные являются text/html/JSON, вы можете использовать третий подход, так как вам не нужно беспокоиться о размере куска. Кроме того, вы можете печатать входящие данные по очереди для целенаправленной отладки.

Если ваши данные представляют собой поток в виде двоичного/базового 64-го изображения, вы должны использовать 1-й подход и читать данные в 4k (обычно используемых) блоках.

UPDATE:

Кстати, вместо страшного DefaultHttpClient Я использую AndroidHttpClient как синглтон и работает гладко :)

+0

Итак, чтение строки ответов не ограничивается файлами, на самом деле имеющими новый символ линии? – eddy

+0

«вместо страшного DefaultHttpClient я использую AndroidHttpClient» - лучше использовать HttpUrlConnection –

+0

, у которых они должны иметь разрывы строк, иначе вы получите буферизацию всего тела ответа в памяти. Вот почему линейное чтение имеет смысл для читаемых человеком файлов: обычно они имеют разрывы строк – injecteer

0

Это важно. Лучшим для производительности является чтение из InputStream в буфер разумного размера. Таким образом вы передаете приличное количество данных за один раз, а затем повторяете одну и ту же операцию тысячу раз. Не всегда полагайтесь на значение заголовка Content-length. Для содержимого gzipped может отображаться неправильный размер.

+0

Я пробовал что-то вроде этого 'char [] buffer = new char [16384]; 'но я всегда получал странные результаты с нежелательными символами в конце строки – eddy

+0

, если вы используете метод read() InputStreamReader, тогда вы должны проверить, возвращает ли он -1, что означает, что больше ничего не нужно читать –

+0

I знаю, и это именно то, что я делал, как показано в моем вопросе 'reader.read (buffer))> 0' – eddy