top / index / prev / next / target / source
日記形式でつづる いがぴょんコラム ウェブページです。
ZIP解凍で ちと困ったので ZIP解凍プログラムを自作 (Java言語製) , 鶴亀メール安定版が更新されていました。
都合により ZIP解凍サンプルを作成しました。圧縮は Jakarta Ant で行う運用の流れにのっているので、普段困るのは解凍側だけです。Antに ZIP解凍はあると思いますけれど、ちょっとした都合 それが使えないのです。というのも今まで使っていたツールにおいて、ファイル日付が うまく更新されないのです。Windows XP へバージョンアップしたのと関係がありそうですが…。ソースコードは下記の通り。170行程度のプログラムで 言語標準APIのみを使っただけでZIP解凍がプログラミングできる世の中なんですねぇ。便利になってきたものです。ただし、このプログラムは 格納されているファイル名が 日本語ファイル名である場合は解凍できない模様です。
/**
* ZIP解凍サンプルプログラム
* Copyright (C) 2001 Tosiki IGA
*
* @author Tosiki IGA
* @version 2001.12.07
* (http://homepage2.nifty.com/igat/igapyon/index.html)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class ZipMelt
{
protected long lSumCount=0;
protected long lSumSize=0;
public static void main(String[] args)
{
if(args.length==0){
System.out.println("解凍したいファイル名を入力してください");
System.out.println("ex: java ZipMelt [解凍したいファイル名]");
System.exit(-1);
}
File fileMelt=new File(args[0]);
if(fileMelt.exists()==false){
System.out.println("指定のファイル["+args[0]+"]が見つかりませんでした.");
System.exit(-2);
}
try{
new ZipMelt().process(fileMelt);
}catch(IOException ex){
System.out.println(ex.toString());
}
}
protected void process(File fileMelt)
throws IOException
{
ZipInputStream inStream=new ZipInputStream(new FileInputStream(fileMelt));
for(boolean isZipEntryFound=false;;isZipEntryFound=true){
ZipEntry entry=inStream.getNextEntry();
if(entry==null){
if(isZipEntryFound==false){
throw new IOException("ZIPエントリが1つも見つかりませんでした");
}
break;
}
processEntry(inStream,entry);
inStream.closeEntry();
}
inStream.close();
java.text.NumberFormat numFormat=java.text.NumberFormat.getInstance();
System.out.println("計 "+numFormat.format(lSumCount)+" 個");
System.out.println(" "+numFormat.format(lSumSize)+" byte");
}
protected void processEntry(ZipInputStream inStream,ZipEntry entry)
throws IOException
{
if(entry.isDirectory()){
processEntryDirectory(entry);
}else{
processEntryFile(inStream,entry);
}
}
protected void processEntryDirectory(ZipEntry entry)
throws IOException
{
File fileDir=new File(entry.getName());
if(fileDir.exists()){
if(fileDir.isDirectory()==false){
System.out.println("作成しようとしたディレクトリ["+entry.getName()+"]と同名ファイルが存在します.");
}
}else if(fileDir.mkdirs()==false){
System.out.println("ディレクトリ["+entry.getName()+"]の作成に失敗.");
}
}
protected void processEntryFile(ZipInputStream inStream,ZipEntry entry)
throws IOException
{
CRC32 crc32=new CRC32();
File fileOut=new File(entry.getName());
String strStatus=null;
if(fileOut.exists()){
if(fileOut.lastModified()==entry.getTime()){
// 同一
}else if(fileOut.lastModified()<entry.getTime()){
strStatus="更新"+getDiff(entry.getTime()-fileOut.lastModified());
}else{
strStatus="後退"+getDiff(fileOut.lastModified()-entry.getTime());
}
}else{
// 新規
}
if(strStatus!=null){
System.out.println(strStatus+" "+fileOut.getName());
}
BufferedOutputStream outStream=new BufferedOutputStream(new FileOutputStream(fileOut));
byte[] byteBuf=new byte[8192];
for(;;){
int iReadLen=inStream.read(byteBuf);
if(iReadLen==(-1)){
break;
}
outStream.write(byteBuf,0,iReadLen);
crc32.update(byteBuf,0,iReadLen);
}
outStream.flush();
outStream.close();
if(entry.getCrc()!=(-1)
&& entry.getCrc()!=crc32.getValue()){
throw new IOException("CRC-32チェックサムエラー:"+fileOut.getName());
}
fileOut.setLastModified(entry.getTime());
// 統計情報の更新
lSumCount++;
lSumSize+=entry.getSize();
}
protected static String getDiff(long lDiff)
{
if(lDiff<0){
lDiff=(-lDiff);
}
if(lDiff<60*1000){
return ""+(lDiff/1000)+"秒";
}else if(lDiff<60*60*1000){
return ""+(lDiff/60/1000)+"分";
}else if(lDiff<24*60*60*1000){
return ""+(lDiff/60/60/1000)+"時";
}else{
return ""+(lDiff/24/60/60/1000)+"日";
}
}
}
このプログラムがバグっていたら困るのですけれども、まあ 従来の ファイル更新日付がずれるのよりはずっとマシかも (とにかくバグっていないことを祈る) CRC-32チェックサムを行っていますが、そもそも CRC-32チェックサムについてはについては詳しくないのであった。でも比較を実施して一致しているのだから、まあ 実装は間違っていないのでしょう (苦笑)
鶴亀メールの安定版が更新 (153: 2001/12/02) されました。