001 /*
002 * Copyright (c) 2009 The openGion Project.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013 * either express or implied. See the License for the specific language
014 * governing permissions and limitations under the License.
015 */
016 package org.opengion.fukurou.util;
017
018 import java.io.BufferedInputStream;
019 import java.io.BufferedOutputStream;
020 import java.io.File;
021 import java.io.FileInputStream;
022 import java.io.FileNotFoundException;
023 import java.io.FileOutputStream;
024 import java.io.IOException;
025 import java.util.ArrayList;
026 import java.util.List;
027 import java.util.zip.ZipEntry;
028 import java.util.zip.ZipInputStream;
029 import java.util.zip.ZipOutputStream;
030
031 /**
032 * ZipFileUtil.java は、ZIPファイルの解凍?圧縮を行うためのUtilクラスです?
033 *
034 * @og.group ユー?リ?
035 *
036 * @version 4.1
037 * @author Hiroki Nakamura
038 * @since JDK5.0,
039 */
040 public final class ZipFileUtil {
041
042 /** ファイル読み込み時?バッファサイズ */
043 private static final int BUF_SIZE = 1024;
044
045 /**
046 * 全てスタ??メソ?のためインスタンスの作?を禁止します?
047 */
048 private ZipFileUtil() {};
049
050 /**
051 * 引数に?されたZIPファイルをフォル?解凍します?
052 * 解凍?のファイルが存在する場合でも?上書きされます?で注意下さ??
053 *
054 * @og.rev 4.1.0.2 (2008/02/01) 新規追?
055 * @og.rev 4.3.1.1 (2008/08/23) mkdirs の戻り?判?
056 * @og.rev 4.3.3.3 (2008/10/22) mkdirsする前に存在チェ?
057 * @og.rev 5.1.9.0 (2010/08/01) 更新時刻の設?
058 *
059 * @param targetPath 解凍?のフォル?
060 * @param zipFileName 解凍するZIPファイル
061 *
062 * @return 解凍されたZIPファイルの?
063 */
064 public static List<String> unCompress( final String targetPath, final String zipFileName ) {
065 // 解凍?フォル??末尾?/'又?'\'でなければ区??を挿入
066 String tmpPrefix = targetPath;
067 if( File.separatorChar != targetPath.charAt( targetPath.length() - 1 ) ) {
068 tmpPrefix = tmpPrefix + File.separator;
069 }
070
071 List<String> list = new ArrayList<String>();
072 ZipInputStream zis = null;
073 ZipEntry entry = null;
074 BufferedOutputStream out = null;
075 String fileName = null;
076 File tmpFile = null;
077 try {
078 zis = new ZipInputStream( new BufferedInputStream( new FileInputStream( zipFileName ) ) );
079
080 while( ( entry = zis.getNextEntry() ) != null ) {
081 fileName = tmpPrefix + entry.getName().replace( '/', File.separatorChar );
082 list.add( fileName );
083
084 boolean flag = true; // 4.3.1.1 (2008/08/23) mkdirs の戻り?判?
085 tmpFile = new File( fileName );
086 // ?レクトリの場合?、?身を含?ィレクトリを作?
087 if( entry.isDirectory() ) {
088 // 4.3.3.3 (2008/10/22) 作?する前に存在チェ?
089 if( !tmpFile.exists() ) {
090 flag = tmpFile.mkdirs();
091 }
092 }
093 // ?レクトリの場合?、?身の親となるディレクトリを作?
094 else {
095 // 4.3.3.3 (2008/10/22) 作?する前に存在チェ?
096 if( !tmpFile.getParentFile().exists() ) {
097 flag = new File( fileName ).getParentFile().mkdirs();
098 }
099
100 out = new BufferedOutputStream( new FileOutputStream( fileName ) );
101 byte[] buf = new byte[BUF_SIZE];
102 int count = 0;
103 while( ( count = zis.read( buf ) ) != -1 ) {
104 out.write( buf, 0, count );
105 }
106 out.close();
107 }
108 // 4.3.1.1 (2008/08/23) mkdirs の戻り?判?
109 if( ! flag ) { System.err.println( fileName + " の ?レクトリ作?に失敗しました? ); }
110 // 5.1.9.0 (2010/08/01) 更新時刻の設?
111 long lastTime = entry.getTime();
112 if( lastTime >= 0 ) {
113 flag = tmpFile.setLastModified( lastTime );
114 }
115 if( ! flag ) { System.err.println( fileName + " の 更新時刻の設定に失敗しました? ); }
116 }
117 }
118 catch( FileNotFoundException ex ) {
119 String errMsg = "解凍ファイルが作?できません?ファイル?" + fileName + "]";
120 throw new RuntimeException( errMsg, ex );
121 }
122 catch( IOException ex ) {
123 String errMsg = "ZIPファイルの解凍に失敗しました?ファイル?" + fileName + "]";
124 throw new RuntimeException( errMsg, ex );
125 }
126 finally {
127 Closer.ioClose( zis );
128 Closer.ioClose( out );
129 }
130
131 return list;
132 }
133
134 /**
135 * 引数に?されたファイル又?フィル??に存在するファイルをZIPファイルに圧縮します?
136 * 圧縮レベルは?ォルト?DEFAULT_COMPRESSIONです?
137 * 圧縮ファイルのエントリー??として本来は、圧縮前後?ファイルサイズ、変更日時?CRCを登録する
138 * ?がありますが、ここでは高?化?ため、設定して?せん?特に圧縮後ファイルサイズの取得??
139 * 非常に不可がかかる?
140 * こ?ため、?のアーカイバでは正しく解凍できな?能性があります?
141 * 既にZIPファイルが存在する場合でも?上書きされます?で注意下さ??
142 *
143 * @og.rev 4.1.0.2 (2008/02/01) 新規追?
144 *
145 * @param targetPath 圧縮対象のファイル又?フォル?
146 * @param zipFileName ZIPファイル?
147 *
148 * @return ZIPファイルのエントリーファイル名?
149 */
150 public static List<String> compress( final String targetPath, final String zipFileName ) {
151 List<String> list = new ArrayList<String>();
152 ZipOutputStream zos = null;
153
154 try {
155 zos = new ZipOutputStream( new BufferedOutputStream ( new FileOutputStream( zipFileName ) ) );
156 File target = new File( targetPath );
157
158 // ZIP圧縮処?行いま?
159 addZipEntry( zos, list, target, "", 0 );
160
161 zos.close();
162 }
163 catch( FileNotFoundException ex ) {
164 String errMsg = "ZIPファイルが見つかりません?ファイル?" + zipFileName + "]";
165 throw new RuntimeException( errMsg, ex );
166 }
167 catch( IOException ex ) {
168 String errMsg = "ZIP圧縮に失敗しました?ファイル?" + zipFileName + "]";
169 throw new RuntimeException( errMsg, ex );
170 }
171 finally {
172 Closer.ioClose( zos );
173 }
174
175 return list;
176 }
177
178 /**
179 * ZIP圧縮処?行います?
180 * 引数に?されたFileオブジェクトが?レクトリであれば再帰?呼び出し?
181 * 下層のファイルをエントリーします??、その?レクトリ自身が空である場合??
182 * ?レクトリをエントリー??として設定します?
183 *
184 * @og.rev 4.1.0.2 (2008/02/01) 新規追?
185 * @og.rev 5.1.9.0 (2010/08/01) 更新時刻の設?、BufferedInputStream のスコープを小さくする?
186 *
187 * @param zos ZIP用OutputStream
188 * @param list ZIPファイルのエントリーファイル名?
189 * @param target 圧縮対象のファイルオブジェク?
190 * @param prefix 処?の?レクトリ
191 * @param depth 階層
192 */
193 private static void addZipEntry( final ZipOutputStream zos, final List<String> list, final File target, final String prefix, final int depth ) {
194 // BufferedInputStream in = null;
195
196 try {
197 // ターゲ?がディレクトリの場合?、ファイルが含まれて?かを
198 // チェ?し?空なら?そ??レクトリをエントリーに追?る?(?に'/'が??
199 // 空じゃなければ、?起呼び出?
200 if( target.isDirectory() ) {
201 File[] fileList = target.listFiles();
202 if( fileList.length == 0 ) {
203 list.add( prefix + target.getName() );
204 ZipEntry entry = new ZipEntry( prefix + target.getName() + '/' );
205 zos.putNextEntry( entry );
206 zos.closeEntry(); // ?レクトリのエントリーは空で作?する?がある。?、FindBugsはエラー
207 }
208 else {
209 for( int i = 0; i < fileList.length; i++ ) {
210 // 再起呼び出しを行う際?圧縮対象にフォル??された場合?
211 // ??の再起処?は、エントリーにフォル??パスを含めな??する?
212 String nextPrefix = "";
213 if( depth > 0 ) {
214 nextPrefix = prefix + target.getName() + '/';
215 }
216 addZipEntry( zos, list, fileList[i], nextPrefix, depth + 1 );
217 }
218 }
219 }
220 // ターゲ?がファイルの場?
221 else {
222 list.add( prefix + target.getName() );
223 ZipEntry entry = new ZipEntry( prefix + target.getName() );
224 entry.setTime( target.lastModified() ); // 5.1.9.0 (2010/08/01) 更新時刻の設?
225 zos.putNextEntry( entry );
226 BufferedInputStream in = null;
227 try {
228 in = new BufferedInputStream( new FileInputStream( target.getAbsolutePath() ) );
229 byte[] buf = new byte[BUF_SIZE];
230 int count;
231 while( ( count = in.read( buf, 0, BUF_SIZE ) ) != -1 ) {
232 zos.write( buf, 0, count );
233 }
234 }
235 finally {
236 // in.close();
237 Closer.ioClose( in );
238 }
239 zos.closeEntry();
240 }
241 }
242 catch( FileNotFoundException ex ) {
243 String errMsg = "圧縮対象のファイルが見つかりません?ファイル?" + target.getName() + "]";
244 throw new RuntimeException( errMsg, ex );
245 }
246 catch( IOException ex ) {
247 String errMsg = "ZIP圧縮に失敗しました?ファイル?" + target.getName() + "]";
248 throw new RuntimeException( errMsg, ex );
249 }
250 // finally {
251 // Closer.ioClose( in );
252 // }
253 }
254
255 /**
256 * ファイルの圧縮また?解凍を行います?
257 *
258 * @og.rev 4.1.0.2 (2008/02/01) 新規追?
259 *
260 * 使用方?: java [comp or uncomp] [targetPath] [zipFileName]
261 * 第1引数 : comp:圧縮 uncomp:解?
262 * 第2引数 : 圧縮?圧縮対象のファイル又?フォル?解凍時:解凍?のフォル?
263 * 第3引数 : ZIPファイル?
264 *
265 * @param args パラメータ
266 */
267 public static void main( final String[] args ) {
268 String usage = "Usage: java [comp or uncomp] [targetPath] [zipFileName]";
269 if( args.length < 3 ) {
270 System.out.println( usage );
271 return;
272 }
273
274 // 開始時?
275 long start = System.currentTimeMillis();
276
277 List<String> list = null;
278 if( "comp".equals( args[0] ) ) {
279 list = compress( args[1], args[2] );
280 }
281 else if( "uncomp".equals( args[0] ) ) {
282 list = unCompress( args[1], args[2] );
283 }
284 else {
285 System.out.println( usage );
286 return;
287 }
288
289 if( list != null ) {
290 // 結果を表示
291 for( String fileName : list ) {
292 System.out.println( fileName );
293 }
294 // 処?間を表示
295 // System.out.println( "処??: " + String.valueOf( System.currentTimeMillis() - start ) + "(ms)" );
296 System.out.println( "処??: " + ( System.currentTimeMillis() - start ) + "(ms)" );
297 }
298 }
299 }