2008-08-28 14 views
5

J'utilise actuellement la fonction suivante pour faire un simple HTTP GET.Existe-t-il une raison d'utiliser BufferedReader sur InputStreamReader lors de la lecture de tous les caractères?

public static String download(String url) throws java.io.IOException { 
    java.io.InputStream s = null; 
    java.io.InputStreamReader r = null; 
    //java.io.BufferedReader b = null; 
    StringBuilder content = new StringBuilder(); 
    try { 
     s = (java.io.InputStream)new URL(url).getContent(); 

     r = new java.io.InputStreamReader(s); 
     //b = new java.io.BufferedReader(r); 

     char[] buffer = new char[4*1024]; 
     int n = 0; 
     while (n >= 0) { 
      n = r.read(buffer, 0, buffer.length); 
      if (n > 0) { 
       content.append(buffer, 0, n); 
      } 
     } 
    } 
    finally { 
     //if (b != null) b.close(); 
     if (r != null) r.close(); 
     if (s != null) s.close(); 
    } 
    return content.toString(); 
} 

Je ne vois aucune raison d'utiliser le BufferedReader puisque je vais juste télécharger tout en séquence. Ai-je raison de penser qu'il n'y a aucune utilité pour le BufferedReader dans ce cas?

Répondre

4

Dans ce cas, je ferais comme vous le faites (utilisez un tableau d'octets pour la mise en mémoire tampon et pas un des tampons de flux).

Il existe cependant des exceptions. Un endroit où vous voyez des tampons (en sortie cette fois) se trouve dans l'API de servlet. Les données ne sont pas écrites dans le flux sous-jacent jusqu'à ce que flush() soit appelé, vous permettant de mettre en mémoire tampon la sortie, puis de vider la mémoire tampon en cas d'erreur et d'écrire une page d'erreur à la place. Vous pouvez tampon d'entrée si vous avez besoin de réinitialiser le flux pour la relecture en utilisant mark (int) et réinitialiser(). Par exemple, vous pouvez peut-être inspecter l'en-tête du fichier avant de décider du gestionnaire de contenu auquel le flux doit être transmis. Non corrélé, mais je pense que vous devriez réécrire votre gestion de flux. Ce modèle fonctionne le mieux pour éviter les fuites de ressources:

InputStream stream = new FileInputStream("in"); 
    try { //no operations between open stream and try block 
     //work 
    } finally { //do nothing but close this one stream in the finally 
     stream.close(); 
    } 

Si vous ouvrez plusieurs flux, essayez nid/finally blocs.

Une autre chose que fait votre code est de faire l'hypothèse que le contenu retourné est encodé dans le jeu de caractères par défaut de votre machine virtuelle (bien que cela puisse être adéquat, selon le cas d'utilisation).

1

Vous avez raison, si vous utilisez BufferedReader pour lire le contenu HTTP et les en-têtes, vous aurez besoin d'InputStreamReader pour pouvoir lire les octets pour les octets. BufferedReader dans ce scénario fait parfois des choses étranges ... surtout lorsqu'il s'agit de lire les en-têtes HTTP POST, parfois vous ne pourrez pas lire les données POST, si vous utilisez le InputStreamReader, vous pouvez lire la longueur du contenu et le lire beaucoup d'octets ...

0

Mon instinct me dit que puisque vous effectuez déjà la mise en mémoire tampon en utilisant le tableau d'octets, il est redondant d'utiliser le BufferedReader.

1

Chaque appel de l'une des méthodes read() de InputStreamReader peut entraîner la lecture d'un ou de plusieurs octets dans le flux d'octets sous-jacent. Pour permettre la conversion efficace des octets en caractères, il est possible de lire plus d'octets à partir du flux sous-jacent que nécessaire pour satisfaire l'opération de lecture en cours.

Questions connexes