top / index / prev / next / target / source

2001-12-07 diary: ZIP解凍ツールの試作

いがぴょんの日記 日記形式でつづる いがぴょんコラム ウェブページです。

old-v2

ZIP解凍ツールの試作

ZIP解凍で ちと困ったので ZIP解凍プログラムを自作 (Java言語製) , 鶴亀メール安定版が更新されていました。

ZIP解凍サンプルの試作

都合により 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) されました。

世間のニュースから () 2001


この日記について