Java でファイルが1つだけ圧縮された zip を解凍するサンプル
ファイルが1つだけ圧縮された zip を解凍するサンプルです。
単一ファイルが圧縮された zip という制限が付くので、あまり汎用的ではないのですが業務アプリを作るときに意外と必要になるのでメモしておきます。
photo credit: TruShu via photopin cc
目次
1. 動作環境
1-1. Java
サンプルを作成したマシンにインストールしてある Java のバージョンは次の通りです。
$ java -version java version "1.7.0_11" Java(TM) SE Runtime Environment (build 1.7.0_11-b21) Java HotSpot(TM) 64-Bit Server VM (build 23.6-b04, mixed mode)
2. zip 解凍のサンプルコード
zip を解凍するメソッドのインタフェースは定義は次の通りです。
/** * ファイルが1つだけ圧縮された zip ファイルを解凍する。 * * 引数の Stream はこのメソッドでそれぞれ BufferedXXXStream に包むので、呼び出し側で包まなくてよい。 * * @param inputStream * zip ファイルの InputStream * @param outputStream * 解凍先の OutputStream * @throws IOException * 解凍処理で例外が発生した場合 */ public static void uncompressSingleFile(InputStream inputStream, OutputStream outputStream) throws IOException;
解凍する zip の InputStream
と解凍先の OutputStream
を受け取ります。
Stream のバッファリングはこのメソッド内で行うので、バッファリングしていない素の Stream を渡してもらいます。
次はコード全体になります。
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.zip.ZipInputStream; public class Zip { /** * InputStream から一度に読み込むバイトサイズ。 */ private static final int BYTE_SIZE = 32768; /** * ファイルが1つだけ圧縮された zip ファイルを解凍する。 * * 引数の Stream はこのメソッドでそれぞれ BufferedXXXStream に包むので、呼び出し側で包まなくてよい。 * * @param inputStream * zip ファイルの InputStream * @param outputStream * 解凍先の OutputStream * @throws IOException * 解凍処理で例外が発生した場合 */ public static void uncompressSingleFile(InputStream inputStream, OutputStream outputStream) throws IOException { ZipInputStream in = new ZipInputStream(new BufferedInputStream( inputStream)); BufferedOutputStream out = new BufferedOutputStream(outputStream); try { if (in.getNextEntry() == null) { throw new IllegalArgumentException("empty file."); } byte[] buf = new byte[BYTE_SIZE]; int size = 0; while ((size = in.read(buf, 0, buf.length)) != -1) { out.write(buf, 0, size); } } finally { if (in != null) { in.close(); } if (out != null) { out.close(); } } } }
InputStream
から一度に読み込むバイトサイズを定数 BYTE_SIZE
として定義しています。
このサイズを大きくすればより高速に zip の解凍処理が終了します。
3. まとめ
zip を解凍してみたけれど空っぽだった場合には IllegalArgumentException
を throw
するようになっています。
これって実行時例外なのでボクは JavaDoc には書かないのですが、一般的にはどうなんでしょうかね。
4. その他の Java に関する記事
Java に関する記事は次の通りです。
気になる記事があったらぜひチェックしてみてください!
-
”Jerseyの@PathParamはスラッシュの間に複数指定できる”VagrantのBoxファイルをカスタマイズして独自のBoxファイルを作成する”バリデーションチェックにJava8のOptionalを使ってスマートに書く(自分比)”ユニットテストの偏りを防ぐ命名規則の付け方”Vagrantで起動したCentOS上のOctopressをホストOSから確認する設定”Vagrantで起動したCentOS上のMySQLにホストOSからログインする設定”Optionalから値を取り出すにはorElseGet()を使う”GoogleGuavaのRangeを使って範囲判定を簡潔に書く”Functions#compose() を使って Function を合成するサンプル(Java8 との比較付き)”Google Guava の Function を使った文字列加工の FluentIterable サンプル”Gradle で Java アプリのプロジェクトを作成して Eclipse にインポートするまでの手順”SDKMAN!(GVM) を使って Mac に Gradle をインストールする”Exec Maven Plugin で maven コマンドでアプリを起動する”Spark を使って JSON を返すシンプルな API を書いてみた”Stream#filter()で絞り込みmap()で処理するコードスニペット”Stream#map()とStream#collect()を使ってListを生成する”Optional型の変数にget()とifPresent()は使わない”Java8 の Optional 型を返す Generics を使ったメソッドを定義する”Java8 の Optional とガード節”Bundler を使ってプロジェクト用の Gem をインストールして Gemfile をバージョン管理ツールに登録するまでの流れ”シェルスクリプトでcdしたいパスにスペースが入っている場合の対処法”CentOSにRubyのBundlerをインストールして使い始める人向けの簡単なまとめ”amazon-ecsを使った検索のエラー原因を確認する”CentOS6.5にGitをソースコードからインストールする”CentOSのバージョン6.5(64ビット)にamazon-ecsをインストールする”CentOSのバージョン6.5(64ビット)にRuby2.1.2をインストールする”mp3splt を実行して "undefined symbol: mp3splt_u_check_if_directory" と出力されたときの対処法”検証用の CentOS をインストールした直後に行う初期設定手順”64ビット版のCentOSをVMwareにインストールできない場合の対処法”参照可能な yum リポジトリを確認する yum コマンドとワンライナー”yum のリポジトリ ATrpms を参照できるように設定する”scp を使ってファイルのコピーを実行したら "command not found" と表示されたときの対処法”scp コマンドを yum を使って CentOS にインストールする”yum が参照するミラーサイトの baseurl を変更して日本国内のものに設定する”CentOS に yum-plugin-priorities プラグインをインストールする”Linuxでmp3をお手軽に結合する”シェルスクリプトでメールを送信する”ロードアベレージを監視するシェルスクリプトを作成してみた”保存ダイアログを表示させてファイルをダウンロードさせる方法”Error オブジェクトの種類と独自例外オブジェクトの作成方法”昭和記念公園で快適に過ごすために覚えておきたいこと”海の公園潮干狩りレポート 2014年版”GTMatrix の診断結果でF判定になった項目の対策まとめ”Tomcatの再起動はworkディレクトリも削除しておいた方が無難”JavaScriptなどをフォーマットするGruntプラグイン grunt-jsbeautifier を使ってみる”Eclipse がエラーメッセージを出力して起動しなくなった場合の対処法”Markdown記法のテキストに書いたソースコードをシンタックスハイライトするプラグイン”子どもの初めての習い事に水泳を選んだ理由”横浜「海の公園」の潮干狩り計画(2014)を立ててみた”GoogleMapsAPIを使って緯度・経度からMarkerを作成する方法”ブログを本格的に始めて3ヶ月経って分かったこと”GoogleMapsAPIを使ってMarkerを削除する方法”GoogleMapsAPIを使ってMarkerの表示と非表示を切り替える方法”Grunt の grunt-contrib-watch を使うと CPU 使用率が上がるので spawn: false を試してみた結果”BOSE のスピーカー Companion2 Series III の購入を検討されている方に”BootstrapValidator の基本的なバリデーションを試すサンプルを作成しました”TwitterBootstrap3 用のバリデーションチェックプラグイン BootstrapValidator の導入から Live チェックまでを試してみた”JavaScript のクラス定義”InputStream に格納されているストリームデータのサイズを取得する”Grunt + QUnit + PhantomJS でテストを自動実行してくれる環境を構築する”GoogleMaps の JavaScript API(v3) を使って、常に1つの InfoWindow だけ表示されるように制御する”GoogleMap サンプルのプロジェクトに Grunt の LiveReload を有効にする設定を追加しました”GitHub にアップされているブランチをローカルに取り込む”GoogleMaps の JavaScript API (v3) を使って地図上に複数の Marker を表示するサンプル”Sublime Text3 で JavaScript を書くために設定したプラグインとキーバインド”Sublime Text3 で Markdown のシンタックスハイライトを有効にする手順”TwitterBootstrap3 をベースにした画面に GoogleMap を埋め込む”Sublime Text3 に SublimeLinter-jshint をインストールしてみた”GoogleMap の Marker に InfoWindow を設定するサンプル”Sublime Text3 のインストール直後に行った設定メモ”GoogleMap を使って住所から緯度・経度を計算する”プロフィールページを追加しました”住所から GoogleMap を表示するサンプル”Android アプリで ActionBar の背景色を変更する方法”Android アプリで "external/chromium/net/disk_cache/stat_hub.cc:216" とエラーメッセージが表示された場合の対処法”Android アプリで特定の Activity が呼ばれたらアプリを終了させる方法”Android の非同期処理を行う Loader の起動方法”Underscore.js の template を使うときは HTML にテンプレートを書こう”JSON をオブジェクトに変換するときに注意したいこと”Android アプリ開発で "cannot perform this action inside of onloadfinished" とエラーメッセージが表示された場面の対処法”Android アプリ開発で "Unable to resolve target 'android-16'" などとエラーメッセージが表示された場合の対処法”第24節 ミランvsボローニャ に関する記事ふりかえり”Daft Punk 素人がヘビーローテーションしている YouTube 動画10選”One Direction - "Story of My Life"”Underscore.js の template を使ってドリルダウンを実装するスニペット”jQuery を使って表示する画像を setInterval を使って切り替える”jQuery を使ってページの opacity を徐々に上げて fadeIn して見せる”Underscore.js の template と each を使って JSON から select タグを生成する”Stinger3 に Pocket ボタンを設置しました”Stinger3 に Feedly ボタンを設置しました”Stinger3 の single.php で使われている style.css をカスタマイズ”jQuery を使ってタグに設定されているクラスをすべて取り除いた後に指定のクラスに変更する”opencsv の HeaderColumnNameTranslateMappingStrategy を使って CSV を Bean に変換する”opencsv の HeaderColumnNameMappingStrategy を使って CSV を Bean に変換する”opencsv の ColumnPositionMappingStrategy を使って CSV を Bean に変換する”spring framework を使ったデスクトップアプリ(standalone app)で context から getBean でオブジェクトを取得する。@Autowired による紐付け”jsvc を使って daemon として起動した Tomcat のプロセス数が2つなのは正しい”Stinger3 の追尾式 SNS ボタンを削除する方法”spring framework を使ったデスクトップアプリ(standalone app)で maven-jar-plugin を使って作成した JAR を java コマンドで実行する”Tomcat7 を jsvc で起動する手順”spring framework を使ったデスクトップアプリ(standalone app)で context から getBean でオブジェクトを取得する”指定した年月の日付を Calendar オブジェクトの一覧で取得する”リストに格納されているオブジェクトを marshal する場合に付与すると便利な @XmlElementWrapper アノテーション”ClassLoader を使って getResourceAsStream で取得したファイルを UTF-8 で読み込む”JAXB を使ってオブジェクトを marshal する際に要素名を指定する方法”JAXB を使ってオブジェクトを marshal するために忘れてはいけない2つのこと”相模原市にある銀河アリーナでスケートを楽しむ”MUSH&Co. "明日も"”「領」と書かれた車のナンバープレートを見た!”Jersey で POST 送信処理後にダイレクトする方法”Android アプリでタイムゾーンを Asia/Tokyo で現在時刻を取得する”jQuery を使ってファイルアップロードフォームのファイルが選択されているかを確認する方法”jQuery を使ってチェックボックスのチェックを付けたり外したりするコードスニペット”9円!!”レスポンスにサムネイル画像を返す API のサンプル”ImageMagick を使ってサムネイル画像を作成する方法”ImageMagick を使って画像を結合する方法”ImageMagick を使って Exif を取り除く方法”Maven で作成したプロジェクトのソースコードを JAR にする方法”Spring の Scheduled アノテーションを使った cron サンプル”Spring の設定ファイル applicationContext.xml の内容をプロパティファイルに切り出す”MySQL の JDBC ドライバで設定しておきたい rewriteBatchedStatements プロパティ”SpringJDBC が発行する SQL をログに出力する”Spring の DataSource に DBCP を使用する”JUnit4 のパラメータ化テストは4通りの方法で書ける”JUnit4 の Enclosed を使ったテストクラスサンプル”JUnit4 で JavaBeans の assertThat を簡潔に書きたい”JUnit4 で List の assertThat を簡潔に書きたい”AgeFileFilter を使ったフィルタ処理のサンプル”SizeFileFilter を使ったフィルタ処理のサンプル”DirectoryFileFilter を使ったフィルタ処理のサンプル”海老名サービスエリアに徒歩で行ってきました”commons-io に見るファイル操作処理のヒント(FilenameUtils編)”Commons IO の LineIterator#isValidLine メソッドをオーバーライドしたサンプル”プロセスの起動を確認するプログラム”配列の内容をファイルに書き込む”拡張子を指定したフィルタの実装サンプル”opencsv を使って CSV ファイルの読み込み開始行を指定する”opencsvの検証をしてみた”commons-io に見るファイル操作処理のヒント(FileUtils編その2)”ファイルを読み込んでその内容を保持する”プログラミングの「面倒くせー」を減らす試み”Redcarpet を使って Markdown をパースする”commons-io に見るファイル操作処理のヒント(FileUtils編その1)”commons-io に見るファイル操作処理のヒント(IOUtils編)”commons-io に見るファイル操作処理のヒント(FileBasedTestCase編)”SQL で表現する階層関係のモデル”Github に人間認定されなくなった”ビジネスメールの言い回しテンプレート”こどもの国の屋外プールに行ってきた”Maven で Web アプリ用のプロジェクトを作成してからコーディングを着手するまでにやること”Android アプリで Google Analytics へトラッキングするサンプルクラス”電子政府推奨暗号リスト”より安全にパスワードを保存するために考えること”初めてのアンドロイドアプリ開発振り返り”ローカルブランチの確認と切り替え方法”ファイルに関するユーティリティ”ディレクトリに関するユーティリティ”WebView からデフォルトブラウザを開く”位置情報取得に関する覚え書き、その2”AlertDialog の背景をタップできなくする”位置情報取得に関する覚え書き”AlertDialog がキャンセルされたときに処理を行うスニペット”with_index メソッド”ImageMagick を使って画像の縦横サイズを縮小する”ファイルの拡張子が JPG であるかを問い合わせるスニペット”画像ファイルを選別するFilenameFilter”画像ファイルのサイズ(縦横じゃなくて容量)を取得するスニペット”サーブレットでクラスパス上にあるプロパティファイルを参照するスニペット”Jetty でシンプルなプロジェクトを作成してみた”google-gson でシリアライズ・デシリアライズしたサンプル”Java から VBScript を使って Excel を印刷する”IE9 のキャッシュ対策”今年も潮干狩りに行ってきた”amazon-ecs を使って Amazon から関連商品情報を取得するサンプル”no space left と表示されたときの対処法”amazon-ecs を使って Amazon から商品情報を取得するサンプル”CVS でタグ間で変更があったファイルを抽出するスクリプト”VPS に Redmine を設置したときに対処したトラブル”VPS に Nokogiri をインストールしたときのトラブル
Googleアドセンス用(PC)
関連記事
-
-
Stream#map()とStream#collect()を使ってListを生成する
Java8 から導入された Stream API も少しずつ慣れてきて、「そういえばこういうパターン
-
-
Gradle で Java アプリのプロジェクトを作成して Eclipse にインポートするまでの手順
Mac に SDKMAN! を使って Gradle をインストールしたので、実際にプロジェクトを作成
-
-
google-gson でシリアライズ・デシリアライズしたサンプル
これまで Java で JSON を扱うときは JSONIC を使っていたが、google-gson
-
-
ディレクトリに関するユーティリティ
ディレクトリに関するスニペットをいくつか書いた。いつかコピペする日が来ると思うのでメモしておく。
-
-
Functions#compose() を使って Function を合成するサンプル(Java8 との比較付き)
Java8 と GoogleGuava の Function について コードの違いを書いた。 その
-
-
サーブレットでクラスパス上にあるプロパティファイルを参照するスニペット
よく使うわりにはいつも調べているのでいい加減メモすることにした。 "app.proper
-
-
Jetty でシンプルなプロジェクトを作成してみた
プロトタイプを作成するなら Tomcat よりも Jetty のほうがさらっと出来そうだなぁ、と今さ
-
-
Java8 の Optional 型を返す Generics を使ったメソッドを定義する
Java8 の Optional とガード節 に続いて Java8 の Optional ネタ。今回
-
-
InputStream に格納されているストリームデータのサイズを取得する
Jersey を使った Web アプリを作成中なんですが、 enctype="multipart/f
-
-
レスポンスにサムネイル画像を返す API のサンプル
今回は直接 ImageMagick は関係ありませんが、また画像ネタです。この辺りのことを仕事で扱っ