Apache HttpClient в Java, instream.toString = org.apache.http.conn.EofSensorInputStream

Я получаю страницу с Apache HttpClient и хочу сохранить http-тело ответа сервера в строку, чтобы затем манипулировать этой строкой и печатать ее на консоли.

К сожалению, при запуске этого метода я получаю это сообщение:

17:52:01,862  INFO Driver:53 - fetchPage STARTING
17:52:07,580  INFO Driver:73 - fetchPage ENDING, took 5716
org.apache.http.conn.EofSensorInputStream@5e0eb724

Класс fetchPage:

public String fetchPage(String part){
    log.info("fetchPage STARTING");
    long start = System.currentTimeMillis();

    String reply;

    String searchurl = URL + URL_SEARCH_BASE + part + URL_SEARCH_TAIL;

    HttpClient httpclient = new DefaultHttpClient();
    HttpGet httpget = new HttpGet(searchurl);
    HttpResponse response;
    try {
        response = httpclient.execute(httpget);
        HttpEntity entity = response.getEntity();
        if (entity != null) {
            InputStream instream = entity.getContent();
            int l;
            byte[] tmp = new byte[2048];
            while ((l = instream.read(tmp)) != -1) {
            }
            long elapsedTimeMillis = System.currentTimeMillis()-start;
            log.info("fetchPage ENDING, took " + elapsedTimeMillis);
            reply = instream.toString();
            System.out.println(reply);
            return reply;
        }
    } catch (ClientProtocolException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return null;
}

person Dominik    schedule 02.06.2011    source источник
comment
Здесь важно понять, что toString() в InputStream — это не метод чтения его содержимого как String, а способ получить простое строковое представление самого объекта. Обычно (в том числе и в этом случае) InputStream не имеет полезного строкового представления, которое он может предоставить, поэтому он просто использует значение по умолчанию Object.toString().   -  person ColinD    schedule 02.06.2011


Ответы (1)


Вы вызываете toString на InputStream после того, как он уже прочитан. Вам нужно создать свою строку из массивов байтов. Более простой способ получить версию содержимого String — использовать файл EntityUtils.toString(HttpEntity)

Точная реализация будет выглядеть так:

import org.apache.http.util.EntityUtils;

public String fetchPage(String part){
    log.info("fetchPage STARTING");
    long start = System.currentTimeMillis();

    String reply;

    String searchurl = URL + URL_SEARCH_BASE + part + URL_SEARCH_TAIL;

    HttpClient httpclient = new DefaultHttpClient();
    HttpGet httpget = new HttpGet(searchurl);
    HttpResponse response;
    try {
        response = httpclient.execute(httpget);
        HttpEntity entity = response.getEntity();
        if (entity != null) {
            return EntityUtils.toString(entity);
        }
    } catch (ClientProtocolException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return null;
}
person Joshua    schedule 02.06.2011
comment
Если я добавлю long elapsedTimeMillis = System.currentTimeMillis()-start; прямо перед return EntityUtils.toString(entity);, прошедшее время для процедуры составит около 1300 мс, если я остановлю время после String result = EntityUtils.toString(entity);, а затем return result, это займет около 5500 мс. Вы знаете, почему это так? - person Dominik; 02.06.2011
comment
@Jack: Вероятно, потому, что клиенту не обязательно получать все данные, которые сервер отправляет, в тот момент, когда вы получаете объект. Создание строки требует фактического чтения всего содержимого, отправляемого сервером. - person ColinD; 02.06.2011
comment
@Jack Murphy: EntityUtils.toString(entity) читает поток. Клиент еще не получил все данные. Вы захотите, чтобы последний зафиксировал количество времени передачи. - person Joshua; 02.06.2011