2014-03-18 72 views
0

我正在使用URLConnection,DataInputStream和FileOutputStream下載文件。我正在用在線文件的大小(使用getContentLength())創建一個巨大的字節[]。事情是,當我嘗試下載大文件時,我得到了一個OutOfMemoryError:Java堆空間,這是一種正常行爲。在不知道大小的情況下下載文件

下面是代碼:

URLConnection con; 
    DataInputStream dis; 
    FileOutputStream fos; 
    byte[] fileData = null; 

    URL url = new URL(from); 
    con = url.openConnection();     

    con.setUseCaches(false); 
    con.setDefaultUseCaches(false); 
    con.setRequestProperty("Cache-Control", "no-store,max-age=0,no-cache"); 
    con.setRequestProperty("Expires", "0"); 
    con.setRequestProperty("Pragma", "no-cache"); 
    con.setConnectTimeout(5000); 
    con.setReadTimeout(30000); 

    dis = new DataInputStream(con.getInputStream()); 

    int contentLength = con.getContentLength(); 

    //Taille connue 
    if (contentLength != -1) 
    { 
     fileData = new byte[con.getContentLength()]; 

     for (int x = 0; x < fileData.length; x++) 
     {    
      fileData[x] = dis.readByte(); 

      if (listener != null) 
      { 
       listener.onFileProgressChanged(x, fileData.length); 
      } 
     } 
    } 
    //Taille inconnue 
    else 
    { 
     System.out.println("Attention : taille du fichier inconnue !"); 
     if (undefinedListener != null) 
     { 
      undefinedListener.onUndefinedFile(); 
     } 
     ByteArrayOutputStream stream = new ByteArrayOutputStream(); 
     while (true) 
     { 
      try 
      { 
       stream.write(dis.readByte()); 
      } 
      catch (EOFException ex) 
      { 
       //Fin 
       fileData = stream.toByteArray(); 
       stream.close();    
      } 
     } 
    } 

    dis.close(); 

    //Ecriture 
    fos = new FileOutputStream(file); 
    fos.write(fileData); 
    fos.close();  

我聽說過,我應該將文件分割成塊,以避免它。我知道如何做到這一點,這很容易,但是......如果文件的ContentLength不能從服務器中獲取(getContentLength()== -1),我該怎麼做?如果我不知道它的大小,我應該如何將文件分成塊?

謝謝!

+0

爲什麼你使用'DataInputStream'? – fge

+0

顯示您現在使用的代碼。幾乎肯定有一個簡單的解決方案,它可能涉及Apache Commons'IOUtils'。 – kdgregory

+0

我添加了代碼 – natinusala

回答

0

根本沒有理由爲什麼你應該使用DataInputStream。使用Files

final Path dstFile = Paths.get("path/to/dstfile"); 
Files.copy(url.openStream(), dstFile); 
1

I am creating a huge byte[] with the size of the online file

爲什麼?您不需要文件大小的字節數組。這隻會浪費空間並增加延遲。只需讀取和寫入緩衝區:

while ((count = in.read(buffer)) > 0) 
{ 
    out.write(buffer, 0, count); 
} 

這適用於大於零的任何字節[]緩衝區。我通常使用8192.

對於URLConnection,您不需要內容長度:只需按照上述方法讀取到EOS即可。

+0

我這樣做,它的工作原理,謝謝:)問題是,當你中斷下載(例如關閉窗口),你有一個半下載的文件左= /我如何刪除文件如果下載沒有完全完成? – natinusala

相關問題