`

原-Java压缩解压文件、文件夹的一个工具类

阅读更多

        2010年做项目的时候偶尔要用到压缩解压目录相关操作,本来以为随便网上搜索一下就有,结果找了半天都没找到,无奈去看下apacheCompress的api,自己写了个。,使用了apache的Compress,common-io。

       有一个比较容易出错的地方,有些压缩方法,如果压缩目录中有空文件夹,可能是解压不出来的,

这是因为压缩的时候,只对于文件写了entryName,文件夹的entryName没有写。

这种情况下,zip文件的entry树结构:大概如下:

+目录A/目录B/目录C/文件1

+目录A/目录B/目录D/文件2

 

这种解压的时候如果CD层没有另外的目录,结果与正常的压缩方法没区别,层级目录能正常创建。

但是如果有一个E的空目录和在CD同级的情况,解压完不会有E目录

正常的压缩目录应该为

+目录A

+目录A/目录B

+目录A/目录B/目录C

+目录A/目录B/目录D

+目录A/目录B/目录E

+目录A/目录B/目录C/文件1

+目录A/目录B/目录D/文件2

 

 

附代码:

public final class ZipTools {

    private int bufferLen = 1024 * 1024;

    /**
     * 私有化构造方法,prevents calls from subclass
     */
    private ZipTools() {
        throw new UnsupportedOperationException();
    }

    private ZipTools(int bufferLen) {
        this.bufferLen = bufferLen;
    }

    public static ZipTools getInstance() {
        return new ZipTools(1024 * 1024);
    }

    public static ZipTools getInstance(int bufferLen) {
        return new ZipTools(bufferLen);
    }

    /**
     * 用于单文件压缩
     */
    protected void doCompress(File srcFile, File destFile) throws IOException {
        ZipArchiveOutputStream out = null;
        InputStream is = null;
        try {
            is = new BufferedInputStream(new FileInputStream(srcFile), bufferLen);
            out = new ZipArchiveOutputStream(new BufferedOutputStream(new FileOutputStream(destFile), bufferLen));
            ZipArchiveEntry entry = new ZipArchiveEntry(srcFile.getName());
            entry.setSize(srcFile.length());
            out.putArchiveEntry(entry);
            IOUtils.copy(is, out);
            out.closeArchiveEntry();
        } finally {
            IOUtils.closeQuietly(is);
            IOUtils.closeQuietly(out);
        }
    }

    /**
     * 解压文件
     * @param zipFile
     * @param outDir
     * @throws IOException
     * 90s
     */
    public void doDecompress(String zipFilePath, String outDirStr) throws IOException {
        File zipFile = new File(zipFilePath);
        File outDir = new File(outDirStr);
        ZipArchiveInputStream is = null;
        try {
            is = new ZipArchiveInputStream(new BufferedInputStream(new FileInputStream(zipFile), bufferLen));
            ZipArchiveEntry entry = null;
            while ((entry = is.getNextZipEntry()) != null) {
                if (entry.isDirectory()) {
                    File directory = new File(outDir, entry.getName());
                    directory.mkdirs();
                } else {
                    OutputStream os = null;
                    try {
                        os = new BufferedOutputStream(new FileOutputStream(new File(outDir, entry.getName())),
                                bufferLen);
                        IOUtils.copy(is, os);
                    } finally {
                        IOUtils.closeQuietly(os);
                    }
                }
            }
        } finally {
            IOUtils.closeQuietly(is);
        }
    }

    /**
     *  解压指定zip文件到目录,使用新方法
     * @param outDir 输出到的目录,此目录如果不存在会自动创建
     * @param unZipfileName 需要解压的zip文件名
     * @throws IOException
     * 30s
     */
    public static void unZip(String outDirPath, String unZipfilePath) throws IOException {
        FileOutputStream fileOutStream = null;
        InputStream inputStream = null;
        ZipFile zipFile = null;
        File outDir = new File(outDirPath);
        File unZipfile = new File(unZipfilePath);

        if (!unZipfile.exists()) {
            throw new FileNotFoundException("File to upzip:" + unZipfilePath + " not found!");
        }
        try {
            zipFile = new ZipFile(unZipfile);
            Enumeration<?> e = zipFile.getEntries();
            while (e.hasMoreElements()) {
                ZipArchiveEntry entry = (ZipArchiveEntry) e.nextElement();
                File file = new File(outDir, entry.getName());
                //File file = getRealFileName(outDirPath, entry.getName());
                if (entry.isDirectory()) {
                    file.mkdirs();
                } else {
                    // 如果指定文件的目录不存在,则创建之.
                    File parent = file.getParentFile();
                    if (!parent.exists()) {
                        parent.mkdirs();
                    }
                    try {
                        inputStream = zipFile.getInputStream(entry);
                        fileOutStream = new FileOutputStream(file);
                        IOUtils.copy(inputStream, fileOutStream);
                    } finally {
                        IOUtils.closeQuietly(inputStream);
                        IOUtils.closeQuietly(fileOutStream);
                    }
                }
            }
        } finally {
            ZipFile.closeQuietly(zipFile);
            IOUtils.closeQuietly(inputStream);
        }

    }

    /**
     * 从文件中解压一个指定文件
     * @param fileName
     * @param zipFile
     * @return
     * @throws IOException 
     * @throws ZipException 
     */
    public InputStream readFileFromSingleFile(ZipFile zipFile, ZipArchiveEntry entry) throws IOException {
        InputStream inputStream = zipFile.getInputStream(entry);
        return inputStream;
    }

    /**
     * 把一个目录打包到一个指定的zip文件中
     * @param dirStr           目录绝对地址
     * @param pathName       zip文件内相对结构
     * @throws IOException 
     */
    private void packFiles(ZipArchiveOutputStream out, File dir, String pathName) throws IOException {
        InputStream is = null;
        //返回此绝对路径下的文件
        File[] files = dir.listFiles();
        if (files == null || files.length < 1) {
            return;
        }
        for (int i = 0; i < files.length; i++) {
            File zFile = files[i];
            out.putArchiveEntry(new ZipArchiveEntry(zFile, pathName + zFile.getName()));
            //判断此文件是否是一个文件夹
            if (zFile.isDirectory()) {
                packFiles(out, zFile, pathName + zFile.getName() + "/");
            } else {
                try {
                    //out.putArchiveEntry(new ZipArchiveEntry(pathName + files[i].getName()));
                    is = new BufferedInputStream(new FileInputStream(zFile), bufferLen);
                    IOUtils.copy(is, out);
                } finally {
                    is.close();
                }
            }
        }
    }

    /**
     * 压缩文件或者文件夹
     * @param srcFileStr 待压缩文件或文件夹路径
     * @param destFileStr 目标文件路径
     * @throws IOException
     */
    public void zip(String srcFileStr, String destFileStr) throws IOException {
        File destFile = new File(destFileStr);
        File srcFile = new File(srcFileStr);
        zip(srcFile, destFile);
    }

    /**
     * 压缩文件
     * @param srcFile 待压缩文件或文件夹
     * @param destFile目标压缩文件
     * @throws IOException
     */
    public void zip(File srcFile, File destFile) throws IOException {
        ZipArchiveOutputStream out = null;

        // 如果压缩文件存放目录不存在,则创建之.
        File pfile = destFile.getParentFile();
        if (!pfile.exists()) {
            pfile.mkdirs();
        }
        //如果是文件
        if (srcFile.isFile()) {
            doCompress(srcFile, destFile);
            return;
        } else {
            try {
                out = new ZipArchiveOutputStream(new BufferedOutputStream(new FileOutputStream(destFile), bufferLen));
                packFiles(out, srcFile, "");
                out.closeArchiveEntry();
            } finally {
                IOUtils.closeQuietly(out);
            }
        }
    }

    /**
     * 将压缩文件中部分文件压缩到另外一个文件中
     */
    public void copyEntryToAnother(ZipFile srcFile, File destFile, ArrayList<ZipArchiveEntry> entryList)
            throws IOException {
        ZipArchiveOutputStream out = null;
        FileOutputStream fileOutStream = null;
        InputStream inputStream = null;

        //建立临时目录
        String tempDirStr = System.getProperty("java.io.tmpdir") + "temp"
                + File.separatorChar;
        File tempDir = new File(tempDirStr, String.valueOf(FlowNoGenerator.instance().getFlowNo()));
        tempDir.mkdirs();

        try {
            //解压
            for (ZipArchiveEntry entry : entryList) {
                File file = new File(tempDir, entry.getName());
                if (entry.isDirectory()) {
                    file.mkdirs();
                } else {
                    // 如果指定文件的目录不存在,则创建之.
                    File parent = file.getParentFile();
                    if (!parent.exists()) {
                        parent.mkdirs();
                    }
                    try {
                        inputStream = srcFile.getInputStream(entry);
                        fileOutStream = new FileOutputStream(file);
                        IOUtils.copy(inputStream, fileOutStream);
                    } finally {
                        IOUtils.closeQuietly(inputStream);
                        IOUtils.closeQuietly(fileOutStream);
                    }
                }
            }
            //压缩
            zip(tempDir, destFile);
        } finally {
            FileUtils.deleteQuietly(tempDir);
        }
        IOUtils.closeQuietly(out);
    }
 

}

 

分享到:
评论

相关推荐

    使用Java API进行tar.gz文件及文件夹压缩解压缩.docx

    3.tar.gz或.tgz通常是指将文件打包到一个tar文件中,并将它使用Gzip进行压缩。 一、将两个文件打包到tar.gz 下面的这个例子是将2个文件打包为tar.gz压缩文件。下文代码中的流操作使用了try-with- resources语法,...

    java压缩文件生成带密码的zip包,解压带密码的zip包的工具类

    压缩文件方法 该方法需要引用zip4j的jar文件 单个文件、多个文件压缩 /** * 使用给定密码压缩指定文件或文件夹到指定位置. * * dest可传最终压缩文件存放的绝对路径,也...一个简单的demo 欢迎大家指点,一起提升

    java源码包---java 源码 大量 实例

     Java zip压缩包查看程序,应用弹出文件选择框,选择ZIP格式的压缩文件,可以像Winrar软件一样查看压缩文件内部的文件及文件夹,源码截图如上所示。 Java 数字签名、数字证书生成源码 2个目标文件 摘要:JAVA源码,...

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

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

    JAVA上百实例源码以及开源项目

     Java zip压缩包查看程序,应用弹出文件选择框,选择ZIP格式的压缩文件,可以像Winrar软件一样查看压缩文件内部的文件及文件夹,源码截图如上所示。 Java 数字签名、数字证书生成源码 2个目标文件 摘要:JAVA源码,...

    Java ZiptUtil工具类

    压缩工具类,压缩文件夹 * * @param zipFileName * 打包后文件的名称,含路径 * @param sourceFolder * 需要打包的文件夹或者文件的路径 * @param zipPathName * 打包目的文件夹名,为空则表示直接打包到根,...

    Android端zip压缩与解压.zip

    Android端zip压缩与解压,目前暂时只做zip格式支持,基于Zip4j (http://www.lingala.net/zip4j/)进行扩展成工具类,支持对单个文件,多个文件以及文件夹进行压缩,对压缩文件解压到到指定目录,支持压缩解压使用密码...

    成百上千个Java 源码DEMO 4(1-4是独立压缩包)

    Java编写的显示器显示模式检测程序 2个目标文件 内容索引:JAVA源码,系统相关,系统信息检测 用JAVA编写了一个小工具,用于检测当前显示器也就是显卡的显示模式,比如分辨率,色彩以及刷新频率等。 Java波浪文字制作...

    java源码包4

     Java zip压缩包查看程序,应用弹出文件选择框,选择ZIP格式的压缩文件,可以像Winrar软件一样查看压缩文件内部的文件及文件夹,源码截图如上所示。 Java 数字签名、数字证书生成源码 2个目标文件 摘要:JAVA源码...

    java源码包3

     Java zip压缩包查看程序,应用弹出文件选择框,选择ZIP格式的压缩文件,可以像Winrar软件一样查看压缩文件内部的文件及文件夹,源码截图如上所示。 Java 数字签名、数字证书生成源码 2个目标文件 摘要:JAVA源码...

    java源码包2

     Java zip压缩包查看程序,应用弹出文件选择框,选择ZIP格式的压缩文件,可以像Winrar软件一样查看压缩文件内部的文件及文件夹,源码截图如上所示。 Java 数字签名、数字证书生成源码 2个目标文件 摘要:JAVA源码...

    JAVA上百实例源码以及开源项目源代码

     Java zip压缩包查看程序,应用弹出文件选择框,选择ZIP格式的压缩文件,可以像Winrar软件一样查看压缩文件内部的文件及文件夹,源码截图如上所示。 Java 数字签名、数字证书生成源码 2个目标文件 摘要:JAVA源码,...

    成百上千个Java 源码DEMO 3(1-4是独立压缩包)

    Java编写的显示器显示模式检测程序 2个目标文件 内容索引:JAVA源码,系统相关,系统信息检测 用JAVA编写了一个小工具,用于检测当前显示器也就是显卡的显示模式,比如分辨率,色彩以及刷新频率等。 Java波浪文字制作...

     一.JAVA程序传送到手机的方法:

    到这个文件夹中(注意一定要把同一个游戏的jad和jar两个文件都放入手机,不要解压jar 文件,如果没有JAD的去下个转换软件)  (7) 安全删除硬件(移动硬盘)拔掉USB手机端  (8) 再拨####5282#,会出现JAVA文件夹...

    【JAVA】彻底清理Maven仓库的工具

    maven-cleaner-1.0.0.RELEASE.zip maven使用的越久,下载的垃圾就越多,包括下载失败的,下载错误的...3、编辑bat文件,修改jar包的解压执行路径和maven仓库路径 4、运行bat 或者自己编写java的jar执行命令均可。

    Java操作Ant压缩和解压文件及批量打包Anroid应用

    2. ant.jar提供了强大的工具类,更加方便于我们对压缩与解压的操作。 注意事项: 1. 首先说明一下,关于皮肤或者类似于皮肤的Zip包,实际上公司可能会根据自己的规定或需求,自定义压缩包文件的结尾,实际上大多还是...

    新版Android开发教程.rar

    Android 是一个专门针对移动设备的软件集,它包括一个操作系统,中间件和一些重要的应用程序。 Beta 版 的 Android SDK 提供了在 Android 平台上使用 JaVa 语言进行 Android 应用开发必须的工具和 API 接口。 特性 ...

    【.Net 】Zip操作库

    DotNetZip是一个易于使用,快速,自由操纵类库和工具集压缩文件或文件夹。 zip和解压很简单:与DotNetZip。NET中编写的应用程序在VB,C#中 - 任何。NET语言 - 可以轻松地创建,阅读,摘录,或更新压缩文件。对于单...

    Util:Cisasoft Java 工具类

    Cisasoft Java 工具类 ChineseHelper 汉字繁体简体转换 PinyinHelper 读取汉字,解析拼音 EnglishHelper 英文字符串处理 QRCodeHelper 二维码工具 ImageHelper 图片处理工具,图片格式之间相互转换,图片加文字水印...

Global site tag (gtag.js) - Google Analytics