2017-10-13 2 views
1

私はそれぞれ5GBから6GBまでの大きなファイルを持っています。私の目標は、これらのファイルを圧縮し、ファイルサーブレットを使用して転送することです。私の現在のコードは時間がかかり、ブラウザでタイムアウトセッションが発生します。ファイルを圧縮するより良い方法はありますか?Javaの大きなファイルを圧縮するより良い方法はありますか?

File zipFile=new File(downloadedFileLocation.getAbsolutePath()+"/Download.zip"); 
     FileOutputStream fos = new FileOutputStream(zipFile); 
     ZipOutputStream zos = new ZipOutputStream(fos); 
     for(File f:downloadedFileLocation.listFiles()) { 
      byte[] buffer = new byte[1024]; 
      ZipEntry ze= new ZipEntry(f.getName()); 
      zos.putNextEntry(ze); 
      FileInputStream in = new FileInputStream(f.getAbsolutePath()); 

      int len; 
      while ((len = in.read(buffer)) > 0) { 
       zos.write(buffer, 0, len); 
      } 

      in.close(); 
      zos.closeEntry(); 
      f.delete(); 
     } 
     zos.close(); 
     fos.close(); 

バッファサイズを変更することで違いがありますか?

誰もがより速くzipを実行できる優れた方法を提案できますか?

+0

物理学は「いいえ」と答えています。操作を並列化できない場合は、ファイルのサイズと数が線形になります。 @duffymoのように – duffymo

+0

と言っています。そのため、一部のウェブサイトで「あなたのダウンロードがすぐに準備完了」と表示され、次にリンクを送信するか、URLを利用できるように更新していくクライアント側を使用します。 –

+1

あなたのバッファは非常に小さいです(現代的なサイズは131072以上になります)が、大きな違いを生み出すことはまずありません。圧縮を避けるために、 'zos.setMethod(ZipOutputStream.STORED);'を使用することもできますが、15GBのデータを同期して処理できるとは思いません。それをバックグラウンドでジップし、結果を保存し、完了するまでクライアントにポーリングをさせます。 –

答えて

3

誰もがジッパーはありません、あなたがより速くビュン行うことはできませんが、あなたは「ライブ」それを行うことができます

速く行うことができます任意のより良い方法を提案することができます。

送信する前に、圧縮されたコンテンツを一時ファイルに書き込まないでください。 ServletのOutputStreamに直接書き込んでください。

結果として、圧縮されたまま圧縮されたコンテンツが送信されるため、接続がタイムアウトしなくなり、合計応答時間が短縮されます。

また、リソース管理にはtry-with-resources、使いやすさとエラーメッセージのための新しいNIOファイルクラスを使用する必要があります。

このような何か:

@Override 
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
    resp.setContentType("application/zip"); 
    try (ZipOutputStream zos = new ZipOutputStream(resp.getOutputStream())) { 
     for (File f : downloadedFileLocation.listFiles()) { 
      zos.putNextEntry(new ZipEntry(f.getName())); 
      Files.copy(f.toPath(), zos); 
      Files.delete(f.toPath()); 
     } 
    } 
} 

私はそこにdelete()を残したが、それをこのように行っているとき、あなたがやっているものに応じて、それはおそらく適切ではありません。または、少なくともダウンロードが完了するまで、つまりforループが終了するまで削除しないでください。

関連する問題