2009-03-04 9 views
1

Je suis en train de lire un fichier binaire à distance (par exemple, l'image) à partir d'Internet comme ceci:Résultat inattendu de HttpURLConnection - lecture du fichier binaire à distance

HttpURLConnection connection = (HttpURLConnection) myUrl.openConnection(); //myUrl - URL object pointing for some location 
if(connection.getResponseCode() == 200){ 
    File temp = File.createTempFile("blabla", fileName); //fileName - string name of file 
    FileOutputStream out = new FileOutputStream(temp); 
    int fileSize = Integer.parseInt(connection.getHeaderField("content-length")); 
    int counter = 0; 
    DataInputStream in = new DataInputStream(connection.getInputStream()); 
    byte ch[] = new byte[1024]; 
    System.out.println(counter); 
    while((counter += in.read(ch)) > 0){ 
     out.write(ch); 
     if(counter == fileSize){ 
      out.close(); 
      break; 
     } 
    } 
} 

localement avec le serveur web local (localhost), il fonctionne à la perfection.

Mais. Puis myUrl est l'URL du fichier sur un serveur web distant - il renvoie des résultats inattendus. Par exemple, à partir de sources de fichiers donnés, il semble qu'il répète certains paquets (je pense à cause de la corruption des précédents ou quelque chose) et le fichier résultant est habituellement environ 10% plus gros que l'original à cause de ces répétitions. Le fichier est donc corrompu et ne peut pas être ouvert correctement avec les visionneuses d'images.

Comment puis-je résoudre ce problème?

Répondre

4

read ne lit pas nécessairement le tampon entier (en particulier s'il se trouve à la fin du flux).

donc changer votre boucle:

for (;;) { 
    int len = in.read(ch); 
    if (len == -1) { 
     break; 
    } 
    out.write(ch, 0, len); 
} 

Peut-être que le code mis dans une méthode quelque part.

A noter également:

  • Il n'y a pas d'intérêt à utiliser DataInputStream ici (bien que readFully est souvent utile).
  • ressources Toujours près (comme les ruisseaux) avec l'idiome usuel:

    final Resource resource = acquire(); 
    try { 
        use(resource); 
    } finally { 
        resource.close(); 
    } 
    
  • ne sera probablement pas faire beaucoup de différence, mais une taille de mémoire tampon de 1024 est un peu petite. J'ai tendance à défaut à 8192 arbitrairement.

+0

Juste pour la fin, la plupart des programmeurs Java préfèrent la variante plus courte: \t int len; \t while ((len = in.read (ch))> = 0) { \t \t out.write (ch, 0, len); Enregistre une condition, une pause et réutilise la variable sur la pile, ce qui la rend un peu moins sujette aux erreurs. –

+0

A préfèrent éviter les effets secondaires. Réutiliser les variables n'est pas la meilleure pratique! –