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 }