Zip(Pass)のファイルの解凍時間を短縮する方法

このQ&Aのポイント
  • JavaでZip(Pass)のファイルを効率的に解凍する方法を教えてください。
  • 現在の方法では一つの画像を取り出すのに4秒以上かかってしまいます。
  • ZipFileのgetEntryメソッドを使用する方法など、効率的な実装方法を教えてください。
回答を見る
  • ベストアンサー

Zip(Pass)のファイルの解凍時間の短縮

Zip(Pass)のファイルの解凍時間の短縮 JavaでZip(Pass)のファイルをSDカードから読込む処理を実装してます。 実際にほしいのは1つのEntryだけで現在下記のように実装してますが、 一つの画像(500kb程度)を引き出すのに4秒以上掛かってしまいます。 zf = new ZipFile(new File(filaName), "UTF-8"); zf.setPassword(password.getBytes("UTF-8")); zf.setCheckCrc(true); //since 2008-12-21 for (Iterator<ZipEntry> i = zf.getEntriesIterator(); i.hasNext();) { ze = i.next(); if(ze.getName().equals(pageNo)){ is = zf.getInputStream(ze); bos = new ByteArrayOutputStream(); for (;;) { int size = is.read(); if (size == -1) break; bos.write(size); } is.close(); b= bos.toByteArray(); bos.close(); break; } } zf.close(); もっと効率の良い実装方法ありますでしょうか? Iterator<ZipEntry>を使用せずにZipFileのgetEntry(String)で使えると思いましたがZipEntryが戻りませんでした。 ZipPassはhisidamaさんのサイトからjarを使わせて頂いてます。 http://www.ne.jp/asahi/hishidama/home/tech/soft/java/zip.html 全て展開すると時間が掛かるので必要なEntryだけ取り出して使いたいです。 以上、よろしくお願いします。

  • Java
  • 回答数2
  • ありがとう数13

質問者が選んだベストアンサー

  • ベストアンサー
  • PecoPlus
  • ベストアンサー率76% (144/188)
回答No.1

 こんにちは。 >Iterator<ZipEntry>を使用せずにZipFileの >getEntry(String)で使えると思いましたが >ZipEntryが戻りませんでした  エントリー名は本当に正確ですか?  特にファイルの名前区切り文字は間違っていませんか?  スラッシュだったり、円マークだったりするので、間違っているのではないですか? >もっと効率の良い実装方法ありますでしょうか?  出力は、ByteArrayOutputStream を使っているので、問題ないとして、  入力の方は、InputStream をそのまま使っているのが、最大のボトルネックだと思います。  BufferedInputStream をかませるか、独自のバッファを使うかして、効率よくした方がいいと思います。

masakazu_s
質問者

お礼

回答ありがとうございます。 ご指摘通りgetEntry(String)の引数に誤りがありました。 BufferedInputStreamを使用して半分くらい短縮に成功しましたがまだ仕様を満たせておりません。 現在下記のように実装してます。 ZipFile zf=null; ZipEntry ze=null; BufferedInputStream bis = null; ByteArrayOutputStream bos=null; try { zf = new ZipFile(new File(filaName), "UTF-8"); zf.setPassword(password.getBytes("UTF-8")); zf.setCheckCrc(true); //since 2008-12-21 ze=zf.getEntry(pageNo); bis = new BufferedInputStream(zf.getInputStream(ze)); bos = new ByteArrayOutputStream(); for (;;) { int size = bis.read(); if (size == -1) break; bos.write(size); } bis.close(); b= bos.toByteArray(); bos.close(); zf.close(); } catch (IOException e) {e.printStackTrace();}

その他の回答 (1)

  • salsberry
  • ベストアンサー率69% (495/711)
回答No.2

InputStreamから1バイトずつ読んでByteArrayOutputStreamに書き込んでいるのが効率悪そうに見えます。 試していませんが、そのライブラリではZipEntry.getSize()とInputStream.read(byte[], int, int)は使えないのでしょうか? 標準のZipFileとZipEntryだったらこのように書けばtoByteArray()も不要です。 is = zf.getInputStream(ze); int zeSize = (int)ze.getSize(); byte[] result = new byte[zeSize]; int total = 0; for (;;) { int size = is.read(result, total, zeSize - total); if (size <= 0) break; total += size; }

masakazu_s
質問者

お礼

回答ありがとうございます。 ご指摘通り実装してみたところ若干ですが早くなりました。 しかしカラーのページなど容量が大きいとやはり時間が掛かってしまいます。 もっと短縮できると良いのですがスペック的に限界でしょうか? ちなみにAndroidモバイル端末(Xperia)にて検証してます。

関連するQ&A

  • zipフォルダの解凍

    いつもお世話になっています。 zipフォルダ実行時のことで質問します。 指定のファイルをzipフォルダに格納して、フォルダ名を指定して格納することはできました。 それで、逆に、zipフォルダにどんなファイルがあるかを確かめたいと思ったのですが、可能なのでしょうか? zipフォルダに格納できたので、それを逆に変えてしようとしたのですが、いまいちわかりません。 zipフォルダに格納したソースは以下です。 import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class ZipOutStream_Test { public static void main(String[] args) throws Exception { File zipf = new File("D:/zip_Java.zip"); //zipファイルに埋め込むfile名 File[] files = { new File("directory.txt") }; ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipf)); try { encode(zos,files); } catch (IOException e) { }catch(Exception e) { }finally { zos.close(); } } static byte[] buf = new byte[1024]; public static void encode(ZipOutputStream zos, File[] files) throws Exception { for(File f: files) { if(f.isDirectory() ) { encode(zos, f.listFiles() ); }else { ZipEntry ze = new ZipEntry(f.getPath().replace('\\', '/')); zos.putNextEntry(ze); InputStream is = new BufferedInputStream(new FileInputStream(f)); for (;;) { int len = is.read(buf); if (len < 0) break; zos.write(buf, 0, len); } is.close(); } } } } 宜しくお願いします。

    • ベストアンサー
    • Java
  • PythonでZIP中のZIPを操作する方法

    【PythonでZIPファイル中のZIPファイルを操作したい】 PythonでZIP内のZIPを再帰的に探して操作したいと考えています。 スクリプトを書いてみたのですが、どうもうまくいきません。 どなたかマズところをご教示いただけないでしょうか? 以下のような構造のデータファイルを用意しました。   SampleZip1.zip     Sample1.txt     Sample2.txt     SampleZip1-1.zip       Sample1-1-1.txt       Sample1-1-2.txt     SampleZip1-2.zip       Sample1-2-1.txt       Sample1-2-2.txt 以下がテストスクリプトです。   import zipfile      def listZipFile( fileName, indent ) :   if not zipfile.is_zipfile( fileName ) :     print( "not zip" + indent + fileName )   return      print( "zip" + indent + fileName )      zip = zipfile.ZipFile( fileName, 'r' )      for f in zip.namelist():     listZipFile( f, "¥t"+ indent )      zip.close()      zipFileName = 'SampleZip1.zip'   listZipFile( zipFileName, "¥t" ) が、結果は以下の通りで、ZIPの中のZIPをZIPファイルと判定してくれないみたいです。   >findZip.py   zip SampleZip1.zip   not zip SampleZip1-2.zip   not zip Sample1.txt   not zip Sample2.txt   not zip SampleZip1-1.zip ZIPファイル中のファイルに対してzipfile.ZipFile()を使うのは無理があるのかなぁ? 一時ファイルにでもいったん出さないとダメ? などと想像しているのですが・・・ どなたかよろしくお願いいたします。

  • Zipファイル解凍処理について

    こんにちわ。 Javaの解凍処理について質問です。 Test.zipがあって、その中身が「テスト.xls」とした時、うまく解凍ができません。 Zipファイルの中身が日本語名ではなく、「Test.xls」であれば正常に解凍ができます。 下記の書き方では日本語名のファイルの入ったZipファイルを解凍することはできないのでしょうか? どなたかご教授お願い致します。 String fname = null; FileInputStream fis = null; BufferedInputStream bis = null; ZipInputStream zis = null; ZipEntry zent = null; FileOutputStream fos = null; try { fis = new FileInputStream(FilePath); bis = new BufferedInputStream(fis); zis = new ZipInputStream(bis); byte[] buf = new byte[1024]; int len; // アーカイブ中に含まれるファイル情報の取得 while ((zent = zis.getNextEntry()) != null) { int intResult = zent.toString().indexOf("."); int intLength = zent.toString().length(); //ファイル名の変更(フォルダ名+社員コード)StringBuffer BuffRename = new StringBuffer(); BuffRename.append("D:\\test\\"); BuffRename.append(zent.getName().substring(0,intResult)); BuffRename.append(SyainCd); BuffRename.append(zent.getName().substring(intResult,intLength)); fname = BuffRename.toString(); //書き込みファイルをオープン fos = new FileOutputStream(fname); while (-1 != (len = zis.read(buf, 0, buf.length))) { fos.write(buf, 0, len); } //★★★ fos.close(); } Catch・finallyは省略

  • PHP Zip 開かない

    よろしくお願いします。現在ZIPにしたものをheaderで出力したいのですが、 その場で解凍した際にフォルダを開くことができません無効ですと表示されます。 原因がわからず困っています。ヒントでも頂ければ助かります。 if(isset($_POST["upload"])){ $dir = file_zone; // Zipファイルの保存先 $file = "./Zipfile/" . date("his") .'.zip'; $root = ""; zipDirectory($dir, $file,$root); } function zipDirectory($dir, $file, $root){ $zip = new ZipArchive(); $res = $zip->open($file, ZipArchive::CREATE); if($res){ // $rootが指定されていればその名前のフォルダにファイルをまとめる if($root != "") { $zip->addEmptyDir($root); $root .= DIRECTORY_SEPARATOR; } $baseLen = mb_strlen($dir); $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $dir, FilesystemIterator::SKIP_DOTS |FilesystemIterator::KEY_AS_PATHNAME |FilesystemIterator::CURRENT_AS_FILEINFO ), RecursiveIteratorIterator::SELF_FIRST ); $list = array(); foreach($iterator as $pathname => $info){ $localpath = $root . mb_substr($pathname, $baseLen); if( $info->isFile() ){ $zip->addFile($pathname, $localpath); } else { $res = $zip->addEmptyDir($localpath); } } $zip->close(); } else { return false; } header('Content-Type: application/octet-stream'); header(sprintf('Content-Disposition: attachment; filename="%s"',basename($file))); header(sprintf('Content-Length: %d', filesize($file)) ); readfile($file); }

    • ベストアンサー
    • PHP
  • Zip名 日付

    失礼します、現在指定したディレクトリにzipファイルを作成しているのですが、Zip名の頭に日付を付けたいです。 dateを使用しているのですが上手くいきませんストリームに出力する際のファイル名にdateはうまくいきましたが指定したディレクトリに保存した際のファイル名がうまくいきません。 自身でZipファイルの保存先にdateを使用してみましたがエラーが出てしまいます。 よろしくお願いします。 if(isset($_POST["upload"])){ $dir = file_zone; // Zipファイルの保存先 $file = './Zipfile/test.zip'; $root = ""; zipDirectory($dir, $file,$root); } function zipDirectory($dir, $file, $root){ $zip = new ZipArchive(); $res = $zip->open($file, ZipArchive::CREATE); if($res){ // $rootが指定されていればその名前のフォルダにファイルをまとめる if($root != "") { $zip->addEmptyDir($root); $root .= DIRECTORY_SEPARATOR; } $baseLen = mb_strlen($dir); $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $dir, FilesystemIterator::SKIP_DOTS |FilesystemIterator::KEY_AS_PATHNAME |FilesystemIterator::CURRENT_AS_FILEINFO ), RecursiveIteratorIterator::SELF_FIRST ); $list = array(); foreach($iterator as $pathname => $info){ $localpath = $root . mb_substr($pathname, $baseLen); if( $info->isFile() ){ $zip->addFile($pathname, $localpath); } else { $res = $zip->addEmptyDir($localpath); } } $zip->close(); } else { return false; } header('Content-Type: application/octet-stream'); header(sprintf('Content-Disposition: attachment; filename="%s"', date(ymdhis).basename($file))); header(sprintf('Content-Length: %d', filesize($file)) ); readfile($file); }

    • ベストアンサー
    • PHP
  • ファイル圧縮について。

    ファイル圧縮について質問させてください。 以下のようなメソッドを作成したのですが、 public run(String strFiles[], String strZipFileName) { int i = 0; int iLen = 0; FileInputStream fis = null; FileOutputStream fos = null; ZipOutputStream zos = null; ZipEntry zent = null; byte[] buf = new byte[1024*10*10]; try { fos = new FileOutputStream(strZipFileName); zos = new ZipOutputStream(fos); for (i = 0; i < strFiles.length(); i++) { fis = new FileInputStream(strFiles[i]); zent = new ZipEntry(strFiles[i]); zos.putNextEntry(zent); while (-1 != (iLen = fis.read(buf))) { zos.write(buf, 0, iLen); } zos.flush(); zos.closeEntry(); fis.close(); } } catch(Exception e) { System.err.println(e); } finally { try { zos.close(); // ※1 fos.close(); // ※2 } catch(Exception e) { System.err.println(e); } } } サイズの小さいファイルや、 特定のサイズのファイル(13k程度)を対象とした時、 高い確率で、空の圧縮ファイルが作成される事があります。 ログを出力しながら確認すると、このような現象が起きた場合、 圧縮ファイルをcloseする直前(※1)では作成されたファイルはサイズがあるのですが、 圧縮ファイルをcloseした直後(※2)ではファイルのサイズが0になってしまいます。 また、2台あるサーバの内、1台だけでこの現象が起こっています。 javaのバージョンは1.3です。 何故このような現象が起こってしまうのか、 ご存知の方がいらっしゃいましたら教えていただけないでしょうか。 宜しくお願いします。

    • ベストアンサー
    • Java
  • strutsでファイルダウンロード(WinでOK,linuxでNG)

    strutsでWindowsのexeファイルのダウンロードを実装しましたが、Windows上のtomcatにdeployすると正常にダウンロードできるのに、linux(fedora-core3)上のtomcatにdeployすると、ダウンロードしたファイルがhtmlになってしまいます。 hoge.exeという名前のファイルはダウンロードできるのですが、それが実はテキストで、メモ帳で開くと、ダウンロード画面のhtmlが表示されます。 この状況は何によって生み出されているのでしょうか。 お分かりになる方、ヒントをお願いいたします。 以下にファイルダウンロード部のソース(抜粋)を掲載させていただきます。 ----- 以下ソース ----- protected void download(HttpServletResponse response, String fileType, String filename) { try { // exeファイルのダウンロード時 if (fileType.equals("application/octet-stream")) { response.setHeader("Content-Disposition", "attachment; filename=" + filename); } response.setContentType(fileType); BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filename)); BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream()); byte[] buf = new byte[128]; int size; while ((size = bis.read(buf, 0, buf.length)) != -1) { bos.write(buf, 0, size); } bos.close(); bis.close(); } catch (IOException e) { throw new thisSystemException("could not send file[" + filename + "]"); }

    • ベストアンサー
    • Java
  • 入出力(FileOutputStreamについて)

    以下のコードは独習Javaのコードです。これを実行すればテキストに0~11までの数字が書き込まれるはずなのですが・・・なぜかA~Hが横に並んで書き込まれてます。 どうなってるのかどなたか教えてください。 import java.io.*; class BufferedOutputStreamDemo {  public static void main(String args[])  {   try   {    FileOutputStream fos = new FileOutputStream(args[0]);    BufferedOutputStream bos = new BufferedOutputStream(fos);    for(int i = 0; i <12; i++)    { bos.write(i);    } bos.close();   }   catch(Exception e)   {     System.out.println("Exception : " +e);   }  } }

    • ベストアンサー
    • Java
  • PHP zipファイルのダウンロード

    下記のようなPHPスクリプトにおいて、zip フォルダに画像ファイルの圧縮ファイルを 保存し、ダウンロードしたいんです。ダウンロードの動作はChrome上で確認できてますが、圧縮した、ダウンロードファイルのサイズが0KB で、空なのです。 どこが間違っているか教えていただけますか? [file_zip.php] <?php mb_internal_encoding("UTF-8"); $ftp = ftp_connect("~"); ftp_login($ftp, "~", "~"); $dir = '/storage2/zip'; ftp_chdir($ftp, $dir); // ディレクトリ移動 // Zipクラスロード $zip = new ZipArchive(); // Zipファイル名 $zipFileName = $_POST['zip_filename']; var_dump($zipFileName); // Zipファイル一時保存ディレクトリ $zipTmpDir = '/storage2/zip'; // Zipファイルオープン $result = $zip->open($zipTmpDir.$zipFileName, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE); if ($result !== true) { // 失敗した時の処理 echo '圧縮ファイルをオープンできませんでした'; exit(); } // ここでDB等から画像イメージ配列を取ってくる $image_data_array = array(); array_unshift($image_data_array, $zipTmpDir.$zipFileName); // 処理制限時間を外す set_time_limit(0); foreach ($image_data_array as $filepath) { $filename = basename($filepath); // 取得ファイルをZipに追加していく $zip->addFromString($filename,file_get_contents($filepath)); } $zip->close(); // ストリームに出力 header('Content-Type: application/zip; name="' . $zipFileName . '"'); header('Content-Disposition: attachment; filename="' . $zipFileName . '"'); header('Content-Length: '.filesize($zipTmpDir.$zipFileName)); echo file_get_contents($zipTmpDir.$zipFileName); // 一時ファイルを削除しておく unlink($zipTmpDir.$zipFileName); // header("Location: storage.php"); ?>

    • 締切済み
    • PHP
  • jarファイル内のJava クラスを列挙する

    こんにちは。早速ですが、 与えられたjarファイルからクラスファイルを見つけ出し、その名前・フィールド・メソッド・パラメータ・タイプを列挙させようと思います。 すべてのクラスの関連や、汎化も考慮します。 出力は以下のようにしたいと思います。 Class Class_Name extends Another_Class_name Attribute: Attribute_name : Attribute_type; Methods: Method_name (Parameter_name : Parameter_type) : Return_type; Association: To_the_other_end_class_name; 今のところ、下記のようにjarファイルを読み込むところまで作ってみたのですが、この後のデータ処理が分かりません。 実は、Java自体初心者に近く、締め切りも近いため焦っています。ご教授いただけるととても嬉しいです。 ちなみに環境は、IBM Rational Software Architectです。Java1.4までのサポートですので、genericタイプなしでお願いします。 public class CReader { public static void main (final String[] args) throws Exception { ClassReader cr = new ClassReader("CReader"); ClassNode cn = new ClassNode(); cr.accept(cn, ClassReader.SKIP_DEBUG); JarFile jar = new JarFile(jarfile); Enumeration files = jar.entries(); while (filest.hasMoreElements()) { ZipEntry entry = (ZipEntry)files.nextElement(); System.out.println(entry.getName()); } byte[] buf = new byte[1024]; int readsize = 0; InputStream is = jar.getInputStream(entry); while ((readsize = is.read(buf, 0, 1024)) != -1) { List methods = cn.methods; for(int i=0; i<methods.size(); i++){ MethodNode method = (MethodNode) methods.get(i); if(method.instructions.size() > 0){ ????? } } } is.close(); } }

    • ベストアンサー
    • Java