Estou fazendo uma solicitação de obtenção HTTP para um site para um aplicativo Android que estou fazendo.
Estou usando um DefaultHttpClient e usando HttpGet para emitir a solicitação. Recebo a resposta da entidade e, a partir disso, obtenho um objeto InputStream para obter o html da página.
Em seguida, alterno a resposta da seguinte maneira:
BufferedReader r = new BufferedReader(new InputStreamReader(inputStream));
String x = "";
x = r.readLine();
String total = "";
while(x!= null){
total += x;
x = r.readLine();
}
No entanto, isso é terrivelmente lento.
Isso é ineficiente? Não estou carregando uma grande página da web - www.cokezone.co.uk, portanto o tamanho do arquivo não é grande. Existe uma maneira melhor de fazer isso?
obrigado
Andy
Respostas:
O problema no seu código é que ele está criando muitos
String
objetos pesados , copiando seu conteúdo e executando operações neles. Em vez disso, você deveStringBuilder
evitar criar novosString
objetos em cada anexo e copiar as matrizes de caracteres. A implementação para o seu caso seria algo como isto:Agora você pode usá-
total
lo sem convertê-lo emString
, mas se precisar do resultado como aString
, basta adicionar:Resultado da string = total.toString ();
Vou tentar explicar melhor ...
a += b
(oua = a + b
), ondea
eb
são Strings, copia o conteúdo de ambosa
eb
para um novo objeto (observe que você também está copiandoa
, que contém o acumuladoString
) e está fazendo essas cópias em cada iteração.a.append(b)
, ondea
é aStringBuilder
, anexa diretamente ob
conteúdoa
, para que você não copie a sequência acumulada a cada iteração.fonte
StringBuilder total = new StringBuilder(inputStream.available());
readline
loop é ridículo. Esse padrão deveria ter morrido com o verde de ervilha nos anos 70.Você já tentou o método interno para converter um fluxo em uma string? Faz parte da biblioteca do Apache Commons (org.apache.commons.io.IOUtils).
Então seu código seria esta linha:
A documentação para isso pode ser encontrada aqui: http://commons.apache.org/io/api-1.4/org/apache/commons/io/IOUtils.html#toString%28java.io.InputStream%29
A biblioteca do Apache Commons IO pode ser baixada aqui: http://commons.apache.org/io/download_io.cgi
fonte
Outra possibilidade com o Goiaba:
dependência:
compile 'com.google.guava:guava:11.0.2'
fonte
Acredito que isso seja eficiente o suficiente ... Para obter uma String de um InputStream, eu chamaria o seguinte método:
Eu sempre uso UTF-8. Você poderia, é claro, definir charset como argumento, além do InputStream.
fonte
Que tal isso? Parece dar um melhor desempenho.
Edit: Na verdade, esse tipo de abrange tanto steelbytes quanto Maurice Perry
fonte
Possivelmente um pouco mais rápido que a resposta de Jaime Soriano, e sem os problemas de codificação de vários bytes da resposta de Adrian, sugiro:
fonte
Talvez, em vez disso, leia 'uma linha de cada vez' e junte as strings, tente 'read all available' para evitar a varredura do fim da linha e também para evitar junções de strings.
ou seja,
InputStream.available()
eInputStream.read(byte[] b), int offset, int length)
fonte
Ler uma linha de texto de cada vez e anexar a referida linha a uma cadeia de caracteres individualmente consome muito tempo ao extrair cada linha e a sobrecarga de tantas invocações de métodos.
Consegui obter um melhor desempenho alocando uma matriz de bytes de tamanho decente para armazenar os dados do fluxo e que é substituída iterativamente por uma matriz maior quando necessário, e tentando ler o máximo que a matriz pudesse suportar.
Por alguma razão, o Android falhou repetidamente no download do arquivo inteiro quando o código usou o InputStream retornado por HTTPUrlConnection, então tive que recorrer ao uso de um BufferedReader e um mecanismo de tempo limite rolado manualmente para garantir que eu obtivesse o arquivo inteiro ou cancelasse a transferência.
EDIT: Acontece que, se você não precisa ter o conteúdo recodificado (ou seja, deseja que o conteúdo seja como está ), não deve usar nenhuma das subclasses de Reader. Basta usar a subclasse Stream adequada.
Substitua o início do método anterior pelas linhas correspondentes a seguir para acelerar mais 2 a 3 vezes .
fonte
Se o arquivo for longo, você poderá otimizar seu código anexando a um StringBuilder em vez de usar uma concatenação de String para cada linha.
fonte
fonte
Para converter o InputStream em String, usamos o método BufferedReader.readLine () . Repetimos até o BufferedReader retornar nulo, o que significa que não há mais dados para ler. Cada linha será anexada a um StringBuilder e retornada como String.
E, finalmente, de qualquer classe em que você deseja converter, chame a função
completo
fonte
Estou acostumado a ler dados completos:
fonte