2009-03-04 14 views
1

Ich versuche, eine Remote-Binär-Datei (zB Bild) aus dem Internet wie folgt zu lesen:Unerwartetes Ergebnis von HttpURLConnection - Lesen Remote-Binärdatei

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; 
     } 
    } 
} 

Lokal von mit lokalem Web-Server (localhost) es funktioniert perfekt.

Aber. Dann ist myUrl die URL der Datei auf einem entfernten Webserver - es gibt unerwartete Ergebnisse zurück. Zum Beispiel scheint es aus Quellen von bestimmten Dateien, dass es einige Pakete wiederholt (ich denke wegen der Korruption von früheren oder etwas) und die resultierende Datei ist wegen dieser Wiederholungen normalerweise etwa 10% größer als die ursprüngliche Datei. Die Datei ist also beschädigt und kann nicht korrekt mit Bildbetrachtern geöffnet werden.

Wie kann ich das lösen?

Antwort

4

read liest nicht unbedingt den gesamten Puffer (besonders, wenn es am Ende des Streams ist).

So Ihre Schleife ändern:

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

Vielleicht, dass Code in einer irgendwo Methode setzen.

Beachten Sie auch:

  • Es hat keinen Sinn DataInputStream hier in Verwendung (obwohl readFully oft nützlich ist).
  • Immer in Ihrer Nähe Ressource (wie Streams) mit dem üblichen Idiom:

    final Resource resource = acquire(); 
    try { 
        use(resource); 
    } finally { 
        resource.close(); 
    } 
    
  • Wahrscheinlich wird nicht viel Unterschied machen, aber eine Puffergröße von 1024 ist ein bisschen klein. Ich neige dazu, willkürlich auf 8192 zu setzen.

+0

Gerade für die Fertigstellung, bevorzugen die meisten Java-Programmierer die kürzere Variante: \t int len; \t während ((len = in.read (ch))> = 0) { \t \t out.write (ch, 0, len); \t} Speichert eine Bedingung, eine Pause und wiederverwendet die Variable auf dem Stapel, die es ein wenig weniger fehleranfällig macht. –

+0

A bevorzugen, Nebenwirkungen zu vermeiden. Die Wiederverwendung von Variablen ist keine Best-Practice! –