こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

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だけ取り出して使いたいです。

以上、よろしくお願いします。

投稿日時 - 2010-06-09 18:55:34

QNo.5956714

すぐに回答ほしいです

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

 こんにちは。

>Iterator<ZipEntry>を使用せずにZipFileの
>getEntry(String)で使えると思いましたが
>ZipEntryが戻りませんでした

 エントリー名は本当に正確ですか?
 特にファイルの名前区切り文字は間違っていませんか?
 スラッシュだったり、円マークだったりするので、間違っているのではないですか?

>もっと効率の良い実装方法ありますでしょうか?

 出力は、ByteArrayOutputStream を使っているので、問題ないとして、
 入力の方は、InputStream をそのまま使っているのが、最大のボトルネックだと思います。
 BufferedInputStream をかませるか、独自のバッファを使うかして、効率よくした方がいいと思います。

投稿日時 - 2010-06-09 21:11:02

お礼

回答ありがとうございます。

ご指摘通り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();}

投稿日時 - 2010-06-10 12:03:23

このQ&Aは役に立ちましたか?

11人が「このQ&Aが役に立った」と投票しています

回答(2)

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

投稿日時 - 2010-06-09 21:48:21

お礼

回答ありがとうございます。

ご指摘通り実装してみたところ若干ですが早くなりました。
しかしカラーのページなど容量が大きいとやはり時間が掛かってしまいます。
もっと短縮できると良いのですがスペック的に限界でしょうか?

ちなみにAndroidモバイル端末(Xperia)にて検証してます。

投稿日時 - 2010-06-10 13:06:44

あなたにオススメの質問