Je fais une demande HTTP get à un site Web pour une application Android que je crée.
J'utilise un DefaultHttpClient et j'utilise HttpGet pour émettre la demande. J'obtiens la réponse de l'entité et j'obtiens un objet InputStream pour obtenir le html de la page.
Je passe ensuite en revue la réponse en procédant comme suit:
BufferedReader r = new BufferedReader(new InputStreamReader(inputStream));
String x = "";
x = r.readLine();
String total = "";
while(x!= null){
total += x;
x = r.readLine();
}
Cependant, cela est horriblement lent.
Est-ce inefficace? Je ne charge pas une grande page Web - www.cokezone.co.uk donc la taille du fichier n'est pas grande. Y a-t-il une meilleure manière de faire cela?
Merci
Andy
Réponses:
Le problème dans votre code est qu'il crée beaucoup d'
String
objets lourds , copie leur contenu et effectue des opérations sur eux. Au lieu de cela, vous devez utiliserStringBuilder
pour éviter de créer de nouveauxString
objets à chaque ajout et pour éviter de copier les tableaux de caractères. La mise en œuvre pour votre cas serait quelque chose comme ceci:Vous pouvez maintenant l'utiliser
total
sans le convertir enString
, mais si vous avez besoin du résultat en tant queString
, ajoutez simplement:Résultat de la chaîne = total.toString ();
J'essaierai de mieux l'expliquer ...
a += b
(oua = a + b
), oùa
etb
sont des chaînes, copie le contenu des deuxa
etb
vers un nouvel objet (notez que vous copiez égalementa
, qui contient l' accumulationString
), et vous effectuez ces copies à chaque itération.a.append(b)
, oùa
est aStringBuilder
, ajoute directement leb
contenu àa
, afin de ne pas copier la chaîne accumulée à chaque itération.la source
StringBuilder total = new StringBuilder(inputStream.available());
readline
est ridicule d' avoir tous les extraits de code sur le Web et les applications de la planète réimplémentant une boucle. Ce motif aurait dû mourir avec du vert pois dans les années 70.Avez-vous essayé la méthode intégrée pour convertir un flux en chaîne? Il fait partie de la bibliothèque Apache Commons (org.apache.commons.io.IOUtils).
Ensuite, votre code serait cette ligne:
La documentation pour cela peut être trouvée ici: http://commons.apache.org/io/api-1.4/org/apache/commons/io/IOUtils.html#toString%28java.io.InputStream%29
La bibliothèque Apache Commons IO peut être téléchargée à partir d'ici: http://commons.apache.org/io/download_io.cgi
la source
Une autre possibilité avec Guava:
dépendance:
compile 'com.google.guava:guava:11.0.2'
la source
Je pense que c'est assez efficace ... Pour obtenir une chaîne à partir d'un InputStream, j'appellerais la méthode suivante:
J'utilise toujours UTF-8. Vous pouvez, bien sûr, définir charset comme argument, en plus d'InputStream.
la source
Et ça. Semble donner de meilleures performances.
Edit: En fait, ce type englobe à la fois steelbytes et Maurice Perry
la source
Peut-être un peu plus rapide que la réponse de Jaime Soriano, et sans les problèmes d'encodage multi-octets de la réponse d'Adrian, je suggère:
la source
Peut-être plutôt que de lire «une ligne à la fois» et de joindre les chaînes, essayez de «lire tout disponible» afin d'éviter de rechercher la fin de ligne et également d'éviter les jointures de chaînes.
ie,
InputStream.available()
etInputStream.read(byte[] b), int offset, int length)
la source
La lecture d'une ligne de texte à la fois et l'ajout de ladite ligne à une chaîne individuellement prend du temps à la fois pour l'extraction de chaque ligne et la surcharge de tant d'appels de méthode.
J'ai pu obtenir de meilleures performances en allouant un tableau d'octets de taille décente pour contenir les données de flux, et qui est remplacé de manière itérative par un tableau plus grand si nécessaire, et en essayant de lire autant que le tableau peut contenir.
Pour une raison quelconque, Android n'a pas réussi à télécharger le fichier entier à plusieurs reprises lorsque le code utilisait le InputStream retourné par HTTPUrlConnection, j'ai donc dû recourir à la fois à un BufferedReader et à un mécanisme de délai d'expiration manuel pour m'assurer que j'obtiendrais le fichier entier ou annulerais le transfert.
EDIT: Il s'avère que si vous n'avez pas besoin de ré-encoder le contenu (c'est-à-dire que vous voulez le contenu TEL QUEL ), vous ne devez utiliser aucune des sous-classes de Reader. Utilisez simplement la sous-classe Stream appropriée.
Remplacez le début de la méthode précédente par les lignes correspondantes de la suivante pour l'accélérer de 2 à 3 fois supplémentaires .
la source
Si le fichier est long, vous pouvez optimiser votre code en l'ajoutant à un StringBuilder au lieu d'utiliser une concaténation de chaîne pour chaque ligne.
la source
la source
Pour convertir InputStream en String, nous utilisons la méthode BufferedReader.readLine () . Nous itérons jusqu'à ce que BufferedReader renvoie null, ce qui signifie qu'il n'y a plus de données à lire. Chaque ligne sera ajoutée à un StringBuilder et renvoyée sous forme de chaîne.
Et enfin à partir de n'importe quelle classe où vous souhaitez convertir, appelez la fonction
Achevée
la source
Je suis habitué à lire les données complètes:
la source