2016-07-09 8 views
0

URLからファイルをダウンロードしたい。ファイルサイズは564.31MBです。ここで何が起こっているのかわからない。また、自分のコードがURLからファイルをダウンロードする正しい方法であるかどうかは疑問です。より良い方法があれば、それがなぜこれより優れているのかを詳細に教えてください。ありがとう。ここでjava.lang.OutOfMemoryError:URLから大きなファイルをダウンロードする際のJavaヒープスペース

import org.apache.commons.io.FilenameUtils; 
import java.io.*; 
import java.net.MalformedURLException; 
import java.net.URL; 

/** 
* Created by lukas on 6/30/16. 
*/ 
public class Main { 
    public static void main(String[] args){ 
     try { 
      String link = "https://s.basketbuild.com/uploads/devs/dianlujitao/oneplus3/cm13/cm-13.0-20160621-UNOFFICIAL-oneplus3.zip"; 
      URL url = new URL(link); 
      InputStream inputStream = new BufferedInputStream(url.openStream()); 
      ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 
      int n=0; 
      byte[] buf = new byte[1024]; 
      long duration = System.currentTimeMillis(); 
      while((n=inputStream.read(buf))!=-1){ 
       byteArrayOutputStream.write(buf, 0, n); 
      } 
      duration = System.currentTimeMillis()-duration; 
      System.out.println("Finish in "+duration+"ms"); 

      inputStream.close(); 

      File dir = new File("Output path"); 
      if(!dir.exists()) 
       dir.mkdirs(); 

      String fileBaseName = FilenameUtils.getBaseName(link); 
      String fileExtension = FilenameUtils.getExtension(link); 
      System.out.println("Name: "+fileBaseName+'.'+fileExtension); 
      File outputFile = new File(dir, fileBaseName+'.'+fileExtension); 

      if(!outputFile.exists()){ 
       outputFile.createNewFile(); 
      } 

      FileOutputStream fileOutputStream = new FileOutputStream(outputFile); 
      fileOutputStream.write(byteArrayOutputStream.toByteArray()); 

      //release outputstream 
      byteArrayOutputStream.close(); 
      fileOutputStream.close(); 

      System.out.println("Your download has been finished"); 


     } catch (MalformedURLException e) { 
      e.printStackTrace(); 
      System.out.println("Something unexpected has happened!"); 
     } catch (IOException e) { 
      e.printStackTrace(); 
      System.out.println("Something unexpected has happened!"); 
     } 


    } 
} 

は私のコンソールはこう言われる、

Finish in 133506ms 
Name: cm-13.0-20160621-UNOFFICIAL-oneplus3.zip 
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 
    at java.util.Arrays.copyOf(Arrays.java:3236) 
    at java.io.ByteArrayOutputStream.toByteArray(ByteArrayOutputStream.java:191) 
    at Main.main(Main.java:42) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:498) 
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144) 
+0

[ "java.lang.OutOfMemoryErrorを:Javaのヒープ領域" をどのように扱うかのエラー(64メガバイトのヒープサイズ)]の可能な重複(http://stackoverflow.com/questions/37335/how-to-deal -with-java-lang-outofmemoryerror-java-heap-space-error-64mb-heap) –

+0

ようこそ。質問を書く時間を費やす前に、可能な回答を探すことは良い考えです。通常は、メインのエラーメッセージでグーグルが実行します(この場合、java.lang.OutOfMemoryError:Javaヒープスペースです)。 –

+0

それは2つの質問です。それらを別々に保つことが最善です。通常、「これを行う方法」の質問は、私たちがここにいるのではないので、多くの答えを得られません。 [ask]と[answer]をお読みください。 –

答えて

3
  1. ByteArrayOutputStreamは、ヒープメモリ内のすべてのデータを割り当てます。 )

    OutputStream os = new BufferedOutputStream(new FileOutputStream("myFile.txt"));
  2. のSystem.currentTimeMillis(あなたが変更される場合があり、現在の日付と時刻を与える:正しい方法は、ファイルに直接書き込み、およびI/Oが最適化されるので、ディスクのバッファを使用することです任意の点。期間を計算するのではなく、SystemClock.nanoTime()を使用してください。

+0

ここで 'BufferedOutputStream'を使わないでください。固定サイズのバッファを割り当て、そのデータをチャンク内で読み書きします。 – erickson

+1

@ericksonこれは、BufferedOutputStreamとまったく同じです。あなたの方法は、チャンクがいっぱいであることを保証しません。ネットワークからデータを読み取ることは、一度に1バイトずつ繰り返すこともできます。バッファなしのディスクI/Oは過剰です。 –

+0

チャンクがいっぱいであることを保証する必要はありません。ファイルをダウンロードすると病理学的になります。冗長コピーは過剰です。 – erickson

関連する問題