原-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);
    }
 

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值