2009-03-04 30 views
1

我想讀取遠程的二進制文件(比如圖片)這樣的:意外的結果 - 讀從互聯網上遠程的二進制文件

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

本地與本地Web服務器(本地主機),它的工作原理完美。

但是。然後,myUrl是某個遠程Web服務器上的文件的URL - 它會返回意外的結果。例如,從給定文件的來源看來,它重複了一些軟件包(我認爲是因爲之前的軟件或某些軟件的損壞),並且由此產生的文件通常比原始文件大10%,因爲這會重複。因此,文件已損壞,無法用圖像查看器正確打開。

我該如何解決這個問題?

回答

4

read不一定讀取整個緩衝區(特別是如果它在流的末尾)。

因此改變你的循環:

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

也許把這些代碼在一個方法某處。

還要注意:

  • 有一個在這裏使用DataInputStream沒有點(雖然readFully是相當實用)。
  • 始終關閉資源(如流)與通常的成語:

    final Resource resource = acquire(); 
    try { 
        use(resource); 
    } finally { 
        resource.close(); 
    } 
    
  • 可能不會太大的差別,但1024的緩衝區大小是一個有點小。我傾向於默認爲8192。

+0

就完成,大多數Java程序員選擇比較短的變體: \t INT len個; ((len = in.read(ch))> = 0)\t out.write \t} 保存一個條件,休息並重新使用堆棧上的變量,這使得它不太容易出錯。 – 2009-03-04 16:58:34