[java] 효율적으로 입력 스트림에서 Android 읽기

내가 만들고있는 안드로이드 응용 프로그램을 위해 웹 사이트에 HTTP get 요청을하고 있습니다.

DefaultHttpClient를 사용하고 HttpGet을 사용하여 요청을 발행하고 있습니다. 엔티티 응답을 얻고이 페이지에서 html을 가져 오기위한 InputStream 객체를 얻습니다.

그런 다음 다음과 같이 회신을 순환합니다.

BufferedReader r = new BufferedReader(new InputStreamReader(inputStream));
String x = "";
x = r.readLine();
String total = "";

while(x!= null){
total += x;
x = r.readLine();
}

그러나 이것은 엄청나게 느립니다.

이것이 비효율적인가? 큰 웹 페이지 -www.cokezone.co.uk를 로드하지 않으므로 파일 크기가 크지 않습니다. 더 좋은 방법이 있습니까?

감사

앤디



답변

코드의 문제는 많은 무거운 String객체를 만들고 내용을 복사하고 작업을 수행 한다는 것입니다. 대신, 각 추가에 StringBuilderString객체를 만들지 않고 char 배열을 복사 하지 않도록 사용해야 합니다. 귀하의 사례에 대한 구현은 다음과 같습니다.

BufferedReader r = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder total = new StringBuilder();
for (String line; (line = r.readLine()) != null; ) {
    total.append(line).append('\n');
}

이제 total로 변환하지 않고 사용할 수 String있지만 결과를로 필요하면 String간단히 추가하십시오.

문자열 결과 = total.toString ();

나는 그것을 더 잘 설명하려고 노력할 것입니다 …

  • a += b(나 a = a + b) 여기서 ab문자열, 복사의 내용입니다 모두 a b (당신은 또한 복사합니다 새로운 객체에 a포함, 축적을 String ), 당신은 각각의 반복에 그 사본을 다하고 있습니다.
  • a.append(b), where ais StringBuilder는에 b내용을 직접 추가 a하므로 반복 할 때마다 누적 된 문자열을 복사하지 않습니다.

답변

스트림을 문자열로 변환하기 위해 내장 메소드를 사용해 보셨습니까? Apache Commons 라이브러리 (org.apache.commons.io.IOUtils)의 일부입니다.

그런 다음 코드는 다음 한 줄입니다.

String total = IOUtils.toString(inputStream);

이에 대한 설명서는 http://commons.apache.org/io/api-1.4/org/apache/commons/io/IOUtils.html#toString%28java.io.InputStream%29 에서 찾을 수 있습니다
.

Apache Commons IO 라이브러리는 다음 위치에서 다운로드 할 수 있습니다.
http://commons.apache.org/io/download_io.cgi


답변

구아바의 또 다른 가능성 :

의존: compile 'com.google.guava:guava:11.0.2'

import com.google.common.io.ByteStreams;
...

String total = new String(ByteStreams.toByteArray(inputStream ));


답변

나는 이것이 충분히 효율적이라고 믿습니다 … InputStream에서 String을 얻으려면 다음 메소드를 호출합니다.

public static String getStringFromInputStream(InputStream stream) throws IOException
{
    int n = 0;
    char[] buffer = new char[1024 * 4];
    InputStreamReader reader = new InputStreamReader(stream, "UTF8");
    StringWriter writer = new StringWriter();
    while (-1 != (n = reader.read(buffer))) writer.write(buffer, 0, n);
    return writer.toString();
}

나는 항상 UTF-8을 사용합니다. 물론 InputStream 외에도 charset을 인수로 설정할 수 있습니다.


답변

이건 어때? 더 나은 성능을 제공하는 것 같습니다.

byte[] bytes = new byte[1000];

StringBuilder x = new StringBuilder();

int numRead = 0;
while ((numRead = is.read(bytes)) >= 0) {
    x.append(new String(bytes, 0, numRead));
}

편집 : 실제로이 종류는 스틸 바이트와 모리스 페리 모두를 포함합니다.


답변

Jaime Soriano의 답변보다 다소 빠르며 Adrian의 답변에 멀티 바이트 인코딩 문제가 없으면 다음과 같이 제안합니다.

File file = new File("/tmp/myfile");
try {
    FileInputStream stream = new FileInputStream(file);

    int count;
    byte[] buffer = new byte[1024];
    ByteArrayOutputStream byteStream =
        new ByteArrayOutputStream(stream.available());

    while (true) {
        count = stream.read(buffer);
        if (count <= 0)
            break;
        byteStream.write(buffer, 0, count);
    }

    String string = byteStream.toString();
    System.out.format("%d bytes: \"%s\"%n", string.length(), string);
} catch (IOException e) {
    e.printStackTrace();
}


답변

어쩌면 ‘한 번에 한 줄씩’을 읽고 문자열을 결합하고 줄 끝을 스캔하지 않도록하고 문자열 조인을 피하기 위해 ‘사용 가능한 모든 항목 읽기’를 시도하십시오.

즉, InputStream.available()InputStream.read(byte[] b), int offset, int length)