`

[原]使用Ant实现zip压缩解压功能

阅读更多

[关键词]:ant,zip,unzip,Apache,压缩,解压,中文乱码,ZipEntry
     先前写了一篇blog《使用org.apache.tools.zip实现zip压缩和解压》 ,现对它进行了改进:找出了几个Bug,修改了部分代码,增加了注释,添加了图形界面,打了个可执行包,双就可以运行了。源代码如下,希望大家多提意见。

MyZip.java:

package myzip;
import java.io.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import myzip.AntZip;

/**
 *界面类,调用AntZip类实现压缩解压功能。
 *@version 2009-3-18
 *@author Winty (wintys@gmail.com)
 */
public class MyZip{
    public static void main(String[] args){
        new MyZip(new AntZip());
    }

    public MyZip(AntZip zip){
        this.zip = zip;
        this.latestDir = new File(".");
        buildUI();       
    }

    public void buildUI(){
        jframe = new JFrame();
        jframe.setTitle("MyZip");
        jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jframe.setResizable(false);
        jframe.setSize(230 , 150);
        Dimension screen= Toolkit.getDefaultToolkit().getScreenSize();
        jframe.setLocation((screen.width-jframe.getWidth())/2,
                                     (screen.height-jframe.getWidth())/2);

        jframe.setLayout(null);
        Container contentPane = jframe.getContentPane();

        JButton zipBtn;
        JButton unzipBtn;
        zipBtn = new JButton("压缩");
        unzipBtn = new JButton("解压");
        zipBtn.setSize(60 , 40);
        unzipBtn.setSize(60 , 40);
        zipBtn.setLocation(40,40);
        unzipBtn.setLocation(120 , 40);
        contentPane.add(zipBtn);
        contentPane.add(unzipBtn);

        zipBtn.addActionListener(new ActionHandler());
        unzipBtn.addActionListener(new ActionHandler());

        jframe.setVisible(true);
    }

    private JFrame jframe;
    private AntZip zip;
    private File latestDir;/*记录最近使用的文件夹路径*/

    /*内部类监听器*/
    class ActionHandler implements ActionListener{
        public void actionPerformed(ActionEvent event){
            JFileChooser chooser = new JFileChooser();
            chooser.setCurrentDirectory(latestDir);

            String cmd = event.getActionCommand();
            if(cmd.equals("压缩")){
                chooser.setFileSelectionMode(
                    JFileChooser.FILES_AND_DIRECTORIES);
                chooser.setMultiSelectionEnabled(true);

                int returnVal = chooser.showOpenDialog(jframe);
                if(returnVal == JFileChooser.APPROVE_OPTION) {
                    File[] files = chooser.getSelectedFiles();
                    if(files!=null){
                        zip.doZip(files , files[0].getName());
                        latestDir = files[0].getParentFile();
                    }
                }
            }
            else if(cmd.equals("解压")){
                chooser.setMultiSelectionEnabled(false) ;

                int returnVal = chooser.showOpenDialog(jframe);
                if(returnVal == JFileChooser.APPROVE_OPTION) {
                    File file = chooser.getSelectedFile();
                    if(file!=null){
                        zip.unZip(file);
                        latestDir = file.getParentFile();
                    }
                }
            }

        }
    }
}


AntZip.java:

package myzip;
import java.io.*;
import org.apache.tools.zip.*;
import java.util.Enumeration;
/**
*功能:zip压缩、解压(支持中文文件名)
*说明:使用Apache Ant提供的zip工具org.apache.tools.zip实现zip压缩和解压功能.
*   解决了由于java.util.zip包不支持汉字的问题。
*   使用java.util.zip包时,当zip文件中有名字为中文的文件时,
*   就会出现异常:
*        "Exception  in thread "main " java.lang.IllegalArgumentException
*      at   java.util.zip.ZipInputStream.getUTF8String(ZipInputStream.java:285)
*
*注意:
*   1、使用时把ant.jar放到classpath中,程序中使用import org.apache.tools.zip.*;
*   2、Apache Ant 下载地址:http://ant.apache.org/
*   3、Ant ZIP Online API:
*www.jajakarta.org/ant/ant-1.6.1/docs/mix/manual/api/org/apache/tools/zip/
*   4、本程序使用Ant 1.7.1 中的ant.jar。
*   5、如果只需要Ant的zip压缩功能,不需要Ant的其它功能,
*     那么可以减小ant.jar的大小。方法是用WinRAR打开ant.jar,
*     把没有用到的包和class文件都删除。这样ant.jar体积就减小了。
*   6、ZipEntry的isDirectory()方法中,目录以"/"结尾。
*
*仅供编程学习参考.
*
*Copyright (c) Winty
*http://www.blogjava.net/wintys
*
*@author Winty (wintys@gmail.com)
*@version   2008-8-3
*------------------------------------------------
*可将主函数注释去掉以单独测试AntZip类。
*Compile:
*   javac -cp Ant.jar AntZip.java
*
*Usage:(将ant.jar直接放在当前目录)
*   压缩:java -cp Ant.jar;.  AntZip -zip [directoryName | fileName]...
*   解压:java -cp Ant.jar;.  AntZip -unzip "fileName.zip"
*
*------------------------------------------------
*2009-3-17:
*修正一处Bug,当解压的zip文件中根目录下直接有文件时会出错。
*将unZip()中的if(!parent.exists())改正为:if(parent!=null && !parent.exists())
*
*2009-3-18:
*多处其它修改
*------------------------------------------------
*/

public class AntZip{
    private ZipFile         zipFile;
    private ZipOutputStream zipOut;     //压缩Zip
    private ZipEntry        zipEntry;
    private static int      bufSize;    //size of bytes
    private byte[]          buf;
    private int             readedBytes;
    //用于压缩中。要去除的绝对父路路径,目的是将绝对路径变成相对路径。
    private String deleteAbsoluteParent;
   
    /**
     *构造方法。默认缓冲区大小为512字节。
     */
    public AntZip(){
        this(512);
    }

    /**
     *构造方法。
     *@param bufSize 指定压缩或解压时的缓冲区大小
     */
    public AntZip(int bufSize){
        this.bufSize = bufSize;
        this.buf = new byte[this.bufSize];
        deleteAbsoluteParent = null;
    }
   
    /**
     *压缩文件夹内的所有文件和目录。
     *@param zipDirectory 需要压缩的文件夹名
     */
    public void doZip(String zipDirectory){
        File zipDir = new File(zipDirectory);
        doZip(new File[]{zipDir} , zipDir.getName());
    }

    /**
     *压缩多个文件或目录。可以指定多个单独的文件或目录。而
     *<code>doZip(String zipDirectory)</code>则直接压缩整个文件夹。
     *@param files 要压缩的文件或目录组成的<code>File</code>数组。
     *@param zipFileName 压缩后的zip文件名,如果后缀不是".zip",
     *  自动添加后缀".zip"。
     */
    public void doZip(File[] files , String zipFileName){
        //未指定压缩文件名,默认为"ZipFile"
        if(zipFileName==null || zipFileName.equals(""))
            zipFileName = "ZipFile";

        //添加".zip"后缀
        if(!zipFileName.endsWith(".zip"))
            zipFileName += ".zip";

        try{
            this.zipOut = new ZipOutputStream(
                new BufferedOutputStream(new FileOutputStream(zipFileName)));
            compressFiles(files , this.zipOut , true );
            this.zipOut.close();
        }catch(IOException ioe){
            ioe.printStackTrace();
        }
    }

    /**
     *压缩文件和目录。由doZip()调用
     *@param files 要压缩的文件
     *@param zipOut zip输出流
     *@param isAbsolute 是否是要去除的绝对路径的根路径。因为compressFiles()
     *会递归地被调用,所以只用deleteAbsoluteParent不行。必须用isAbsolute来指明
     *compressFiles()是第一次调用,而不是后续的递归调用。即如果要压缩的路径是
     *E:\temp,那么第一次调用时,isAbsolute=true,则deleteAbsoluteParent会记录
     *要删除的路径就是E:\ ,当压缩子目录E:\temp\folder时,isAbsolute=false,
     *再递归调用compressFiles()时,deleteAbsoluteParent仍然是E:\ 。从而保证了
     *将E:\temp及其子目录均正确地转化为相对目录。这样压缩才不会出错。不然绝对
     *路径E:\也会被写入到压缩文件中去。
     */
    private void compressFiles(File[] files ,
                                            ZipOutputStream zipOut ,
                                            boolean isAbsolute) throws IOException{

        for(File file : files){
            if(file==null)continue; //空的文件对象

            //删除绝对父路径
            if(file.isAbsolute()){
                if(isAbsolute){
                    deleteAbsoluteParent = file.getParentFile().getAbsolutePath();
                    deleteAbsoluteParent = appendSeparator(deleteAbsoluteParent);
                }
            }
            else
                deleteAbsoluteParent = "";

            if(file.isDirectory()){//是目录
                compressFolder(file , zipOut);
            }
            else{//是文件
                compressFile(file , zipOut);
            }
        }
    }

    /**
     *压缩文件或空目录。由compressFiles()调用。
     *@param file 需要压缩的文件
     *@param zipOut zip输出流
     */
    public void compressFile(File file , ZipOutputStream zipOut)
        throws IOException{

        String fileName = file.toString();

        /*去除绝对父路径。*/
        if(file.isAbsolute())
            fileName = fileName.substring(deleteAbsoluteParent.length());
        if(fileName == null || fileName=="")
            return;


        /*因为是空目录,所以要在结尾加一个"/"。
          不然就会被当作是空文件。
          ZipEntry的isDirectory()方法中,目录以"/"结尾.
          org.apache.tools.zip.ZipEntry :
            public boolean isDirectory() {
                return getName().endsWith("/");
            }
          */
        if(file.isDirectory())
            fileName = fileName + "/";//此处不能用"\\"

        zipOut.putNextEntry(new ZipEntry(fileName));

        //如果是文件则需读;如果是空目录则无需读,直接转到zipOut.closeEntry()。
        if(file.isFile()){
            FileInputStream fileIn = new FileInputStream(file);
            while((this.readedBytes = fileIn.read(this.buf))>0){
                zipOut.write(this.buf , 0 , this.readedBytes);
            }
            fileIn.close();
        }

        zipOut.closeEntry();
    }

    /**
     *递归完成目录文件读取。由compressFiles()调用。
     *@param dir 需要处理的文件对象
     *@param zipOut zip输出流
     */
    private void compressFolder(File dir , ZipOutputStream zipOut)
        throws IOException{
       
        File[] files = dir.listFiles();
   
        if(files.length == 0)//如果目录为空,则单独压缩空目录。
            compressFile(dir , zipOut);
        else//如果目录不为空,则分别处理目录和文件.
            compressFiles(files , zipOut , false);
    }
   
    /**
     *解压指定zip文件。
     *@param unZipFileName 需要解压的zip文件名
     */
    public void unZip(String unZipFileName){
        FileOutputStream fileOut;
        File file;
        InputStream inputStream;

        try{
            this.zipFile = new ZipFile(unZipFileName);

            for(Enumeration entries = this.zipFile.getEntries();
                entries.hasMoreElements(); ){

                ZipEntry entry = (ZipEntry)entries.nextElement();
                file = new File(entry.getName());

                if(entry.isDirectory()){//是目录,则创建之
                    file.mkdirs();
                }
                else{//是文件
                    //如果指定文件的父目录不存在,则创建之.
                    File parent = file.getParentFile();
                    if(parent!=null && !parent.exists()){
                        parent.mkdirs();
                    }

                    inputStream = zipFile.getInputStream(entry);

                    fileOut = new FileOutputStream(file);
                    while(( this.readedBytes = inputStream.read(this.buf) ) > 0){
                        fileOut.write(this.buf , 0 , this.readedBytes );
                    }
                    fileOut.close();

                    inputStream.close();
                }  
            }
            this.zipFile.close();
        }catch(IOException ioe){
            ioe.printStackTrace();
        }
    }

   
    /**
     *给文件路径或目录结尾添加File.separator
     *@param fileName 需要添加路径分割符的路径
     *@return 如果路径已经有分割符,则原样返回,否则添加分割符后返回。
     */
    private String appendSeparator(String path){
        if(!path.endsWith(File.separator))
                        path += File.separator;
        return path;
    }

    /**
     *解压指定zip文件。
     *@param unZipFile 需要解压的zip文件对象
     */
    public void unZip(File unZipFile){
        unZip(unZipFile.toString());
    }

    /**
     *设置压缩或解压时缓冲区大小。
     *@param bufSize 缓冲区大小
     */
    public void setBufSize(int bufSize){
        this.bufSize = bufSize;
    }

    //主函数,用于测试AntZip类
    /*
    public static void main(String[] args)throws Exception{
        if(args.length>=2){
            AntZip zip = new AntZip();

            if(args[0].equals("-zip")){
                //将后续参数全部转化为File对象
                File[] files = new File[ args.length - 1];
                for(int i = 0;i < args.length - 1; i++){
                    files[i] = new File(args[i + 1]);
                }

                //将第一个文件名作为zip文件名
                zip.doZip(files , files[0].getName());

                return ;
            }
            else if(args[0].equals("-unzip")){
                zip.unZip(args[1]);
                return ;
            }
        }
       
        System.out.println("Usage:");
        System.out.println("压缩:java AntZip -zip [directoryName | fileName]... ");
        System.out.println("解压:java AntZip -unzip fileName.zip");
    }
    */
}


附件内容:
/MyZip.jar : 打包后的可执行文件,可单独运行,内含org.apache.tools.zip包。运行环境JRE1.6+
/使用Ant实现zip压缩解压功能/ant.jar : 精简后的ant包,只包含org.apache.tools.zip
/使用Ant实现zip压缩解压功能/AntZip.java
/使用Ant实现zip压缩解压功能/MyZip.java

[附件]:使用Ant实现zip压缩解压功能.zip

分享到:
评论

相关推荐

    利用ant.jar解压缩zip包

    利用ant.jar解压缩zip包的工具类,内含ant.jar包,可以解决文件为中文的问题,大家随便看看

    ant操作7zip压缩、解压 tar.gz

    7zip压缩、解压 tar.gz,build.xml在压缩包里面。。。。。。。。。。。。。。

    java zip压缩解压工具解决中文乱码问题

    使用java压缩也解压zip文件方法,解决中文乱码问题。使用java自带的压缩解压算法,会出现中文乱码问题。使用apache io的zip包,有效解决该问题。Ant的压缩解压,也是使用该类。

    AntZip:AntZip 压缩与解压

    AntZip压缩/*** 对传入的目录或者是文件进行压缩* @param srcFile 需要 压缩的目录或者文件* @param destFile 压缩文件的路径*/public void doZip(String srcFile, String destFile) {// zipDirectoryPath:需要...

    采用antzip包来实现解压和压缩功能

    采用antzip包来实现解压和压缩功能,在android中可能有时需要利用一些外部的zip部来提供数据 ,比如换肤等 等 。这时我们就离不开对zip的压缩与解压了。可能有我们都知道android中自身就有包来进行这功能 ,但是对...

    java 操作Zip文件(压缩、解压、加密).zip

    java 操作Zip文件(压缩、解压、加密) zip4j-1.3.2.jar ant-1.10.6.jar

    apache-ant-zip.jar包及用法

    apache-ant-zip.jar包及用法 用过java做压缩或解压的都知道,jdk提供的zip只能按UTF-8格式处理,所有jdk提供的zip不能支持中文文件名,可以采用Apache的zip包解决中文文件名问题。

    java Zip压缩解压

    zip包里面有两个文件,一个是zip封装类,一个是测试类, 还有这个里面需要用到apache的ant.jar包,和junit.jar单元测试包,如果报错请导入上面说的两个包

    解压,压缩zip的ant包

    可以解决中文的的文件,比java.util.zip自带的要好

    分离自Ant的ZIP包可解决中文文件名处理问题

    这个名是名离自ant原码的,由于java.util.zip处理中文文件名时有问题可以用这个包代替那个使用就不会有中文问题了,我加了一个ZipTool.java,这个就是一个示例文件和方法打包文件。 &lt;br&gt;特点: 一、自有原码不...

    解压zip压缩文件,支持多文件目录解压,中文乱码问题

    在使用Java对ZIP压缩文件进行解压的方式中有两种,一种是使用apache提供的ant.jar工具包,但是如果ZIP文件中含有中文名称的文件,在解压后,文件名将出现乱码,另一种是使用Java自身JDK中java.util.zip包下工具类,...

    JAVA解压ZIP多层目录文件(需ant.jar

    完美支持解压zip文件多层文件解压,文件夹,文件,支持中文。

    ant-1.9.12最近解压zip依赖jar包

    这是一个支持zip压缩文件解压依赖的最新jar包,这种解压比java语言自带的解压功能更强大,支持解压时设置特定的编码(如中文“GBK”)功能

    android解压zip乱码处理(包括ant瘦身后的jar)

    在android开发中,有时候需要将文件打包成zip或将zip解压,如果直接用java.util.zip包下面的类会出现中文乱码,如果直接用org.apache.tools.zip(ant包中的压缩功能)会影响项目的编译时间; 故将ant包中文件瘦身,既...

    利用ant api做的遍历并解压各种压缩文件格式的源代码

    利用ant api做的遍历并解压各种压缩文件格式的源代码 支持 zip, (当然) gzip tar gz bz2 bz 文件包括ant.jar, 源代码 有问题可以留言,我会及时回复 ziptest下面是用来做测试的目录。 请解压到 C:\temp\ziptest ...

    JDK ZipEntry压缩中文文件名乱码解决

    项目中碰到问题.jdk zipEntry 压缩中文文件名乱码 ... 如果仅用到压缩,就加入ant.jar 就导致引入了一些不必要的文件,所以我找到Ant1.8的源码,然后只把需要的那一部分编译打包成了一个jar文件,供大家使用

    ant中分离出的用于压缩和解压的部分

    从Apache Ant 中分离出的压缩和解压功能的jar,可用于zip,tar,gzip文件的压缩和解压缩,支持中文名称

    java解压zip或rar压缩文件(源码和jar包)

    java解压zip或rar压缩文件 包括源码和所需要的jar包:apache ant.jar 和 java-unrar-0.3.jar zip文件解压(要使用apache ant.jar以处理中文乱码) rar文件解压(要使用java-unrar-0.3.jar) 具有处理中文乱码功能 代码...

    Java压缩/解压缩zip

    使用Java核心API实现单文件/多文件/整个目录的压缩/解压缩功能,由于自带API(1.6)不支持指定编码方式,因此中文会出现乱码(1.7貌似已经支持指定编码方式),所以还写了一个基于ant包的压缩/解压缩代码。

Global site tag (gtag.js) - Google Analytics