`

[原]使用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,可以编写一个简单的Ant构建文件(build.xml),并使用`unzip`任务来解压缩ZIP文件。例如: ```xml &lt;unzip src="path/to/your.zip" dest="output/directory"/&gt; `...

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

    了解这些基础知识后,我们可以更有效地利用7-Zip和Ant处理文件压缩和解压,特别是在大型项目中,自动化这些过程可以显著提高工作效率。同时,理解XML配置文件如build.xml的内容,可以帮助我们定制化构建流程,满足...

    apache-ant-zip-2.3.jar.zip

    Apache Ant Zip 2.3.jar 特别关注的是处理ZIP文件格式的操作,包括创建、解压和操作ZIP档案中的文件。这个特定的版本2.3可能包含了一些特定的修复或功能改进相对于之前的版本。由于在Maven仓库中找不到这个特定的...

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

    这里我们重点讨论使用两个库:`zip4j`和`Apache Ant`来实现这些功能。 1. **zip4j库**:`zip4j-1.3.2.jar`是一个用Java编写的库,它提供了方便的API来处理Zip文件。以下是一些关键功能: - **压缩文件和目录**:你...

    java Zip压缩解压

    总结来说,"java Zip压缩解压"涉及了Java标准库中的`java.util.zip`包,用于创建和读取ZIP文件;Apache Ant作为构建工具,可能用于自动化压缩和解压过程;而JUnit则用于编写和运行测试,确保代码的正确实现。在实际...

    apache-ant-zip.jar包及用法

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

    java zip 压缩 解压缩 附带ant.jar

    在本主题中,我们将深入探讨如何使用Java来对文件进行zip压缩和解压缩,并提及`ant.jar`的作用。 首先,让我们来看一下`JavaZip.java`这个文件。它很可能包含了一个示例程序,演示了如何使用Java API来压缩和解压缩...

    AntZip:AntZip 压缩与解压

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

    java解压和压缩ZIP文件的功能

    这篇内容将深入讲解如何使用Java实现ZIP文件的压缩和解压功能,并结合给定的`ant.jar`库和`ZipUtil.java`源代码文件来理解其实现原理。 首先,`ant.jar`是Apache Ant的库文件,Ant是一个基于Java的构建工具,它可以...

    java 中 zip压缩文件解压工具类

    本文将深入探讨如何使用Java来处理ZIP文件,特别是针对标题所提及的“java 中 zip压缩文件解压工具类”。我们将讨论核心的Java API,如`java.util.zip`包中的类,并通过一个名为`CompressFileUtils`的工具类来展示...

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

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

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

    这种方法利用了Apache Ant库中的`org.apache.tools.zip.ZipFile`类来实现解压功能。在实际应用中,这种方法非常实用,尤其是在需要处理复杂ZIP文件结构的情况下。 #### 方法参数 该方法接受三个参数: 1. **old...

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

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

    用ant来解压文件

    标题中的“用ant来解压文件”指的是使用Apache Ant这一开源构建工具来处理压缩文件,如.zip或.tar.gz等。Apache Ant是Java生态系统中的一个重要组件,它基于XML来定义项目构建过程,包括编译、打包、测试等任务。在...

    解压,压缩zip的ant包

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

    ant zip jar

    在Java开发中,开发者经常使用ZipOutputStream和ZipInputStream类来创建和解压Zip文件。Zip文件可以包含多个条目,每个条目对应原文件或目录的一个副本。Zip格式支持文件的压缩,但也可以包含未压缩的内容,方便快速...

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

    在Java编程中,处理文件压缩和解压是常见的任务,特别是使用ZIP格式。然而,当涉及到包含中文字符的文件或目录时,可能会遇到乱码问题。这个问题主要源于字符编码的不一致,通常需要正确设置字符集来确保中文字符在...

    apache-ant-1.6.5-bin.zip_ ant 1.6.5_ant_ant-1.6.5_apache ant win

    - 在Windows上设置Ant通常涉及解压这个ZIP文件,设置ANT_HOME环境变量,并将bin目录添加到PATH环境变量中。 4. **使用Ant** - 用户可以通过命令行工具运行Ant,例如使用"ant clean compile"命令来清理并编译项目...

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

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

Global site tag (gtag.js) - Google Analytics