package com.tool.util;import androidx.annotation.Size;import org.apache.commons.compress.archivers.tar.TarArchiveEntry;import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.util.Arrays;import java.util.Enumeration;import java.util.zip.CRC32;import java.util.zip.CheckedOutputStream;import java.util.zip.GZIPInputStream;import java.util.zip.GZIPOutputStream;import java.util.zip.ZipEntry;import java.util.zip.ZipFile;import java.util.zip.ZipInputStream;import java.util.zip.ZipOutputStream;/** * 压缩工具类。 * zip是将文件打包为zip格式的压缩文件。 * gzip是将文件打包为tar.gz格式的压缩文件。 * gzip只能对一个文件进行压缩,如果想压缩一大堆文件,就需要使用tar进行打包了。 */public class CompressUtil {    private static final byte[] ZIP_HEADER_1 = new byte[]{0x1F, (byte) 0x8B, 0x03, 0x04};    private static final byte[] ZIP_HEADER_2 = new byte[]{0x1F, (byte) 0x8B, 0x05, 0x06};    private static final int BUFF_SIZE = 1024;    /**     * 判断文件是否压缩     */    public static boolean isCompressed(@Size(4) byte[] data) {        if (data == null || data.length < ZIP_HEADER_1.length) return false;        byte[] header = Arrays.copyOf(data, ZIP_HEADER_1.length);        return Arrays.equals(header, ZIP_HEADER_1) || Arrays.equals(header, ZIP_HEADER_2);    }    public static byte[] zip(byte[] data) {        ByteArrayOutputStream baos = new ByteArrayOutputStream();        ZipOutputStream zip = new ZipOutputStream(baos);        byte[] result = null;        try {            String name = FileUtil.genNameByDate();            zip.putNextEntry(new ZipEntry(name));            zip.write(data);            zip.closeEntry();            zip.flush();            result = baos.toByteArray();        } catch (IOException e) {            e.printStackTrace();        } finally {            try {                zip.close();            } catch (IOException e) {                e.printStackTrace();            }        }        return result;    }    public static byte[] unzip(byte[] data) {        byte[] buffer = new byte[BUFF_SIZE];        int len;        ByteArrayOutputStream baos = new ByteArrayOutputStream();        ByteArrayInputStream bais = new ByteArrayInputStream(data);        ZipInputStream unzip = new ZipInputStream(bais);        byte[] result = null;        try {            //这里的getNextEntry实际上是从byte数组里面读一段,如果没写这句,则后续解析失败            ZipEntry zipEntry = unzip.getNextEntry();            while ((len = unzip.read(buffer)) != -1) {                baos.write(buffer, 0, len);            }            result = baos.toByteArray();        } catch (IOException e) {            e.printStackTrace();        } finally {            try {                unzip.close();            } catch (IOException e) {                e.printStackTrace();            }        }        return result;    }    public static byte[] gzip(byte[] data) {        ByteArrayOutputStream baos = new ByteArrayOutputStream();        GZIPOutputStream gzip = null;        byte[] result = null;        try {            gzip = new GZIPOutputStream(baos);            gzip.write(data);            gzip.flush();            //gzip这里有点问题,必须close之后再取数据,否则有遗漏            gzip.close();            gzip = null;            result = baos.toByteArray();        } catch (IOException e) {            e.printStackTrace();        } finally {            try {                if (gzip != null) gzip.close();            } catch (IOException e) {                e.printStackTrace();            }        }        return result;    }    public static byte[] ungzip(byte[] data) {        byte[] buffer = new byte[BUFF_SIZE];        int len;        ByteArrayOutputStream baos = new ByteArrayOutputStream();        ByteArrayInputStream bais = new ByteArrayInputStream(data);        byte[] result = null;        GZIPInputStream ungzip = null;        try {            ungzip = new GZIPInputStream(bais);            while ((len = ungzip.read(buffer)) != -1) {                baos.write(buffer, 0, len);            }            result = baos.toByteArray();        } catch (IOException e) {            e.printStackTrace();        } finally {            try {                if (ungzip != null) ungzip.close();            } catch (IOException e) {                e.printStackTrace();            }        }        return result;    }    /**     * ZIP压缩     *     * @param file    待压缩的文件或文件夹     * @param zos     压缩流     * @param baseDir 相对压缩文件的相对路径     */    private static void zip(File file, ZipOutputStream zos, String baseDir) {        if (file.isDirectory()) {            File[] files = file.listFiles();            for (File f : files) {                zip(f, zos, baseDir + file.getName() + File.separator);            }        } else if (file.isFile()) {            FileInputStream fis = null;            try {                fis = new FileInputStream(file);                ZipEntry zipEntry = new ZipEntry(baseDir + file.getName());                zos.putNextEntry(zipEntry);                int len;                byte[] buffer = new byte[BUFF_SIZE];                while ((len = fis.read(buffer)) != -1) {                    zos.write(buffer, 0, len);                }                zos.closeEntry();            } catch (FileNotFoundException e) {                e.printStackTrace();            } catch (IOException e) {                e.printStackTrace();            } finally {                try {                    if (fis != null) fis.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }    /**     * Zip压缩     *     * @param srcFile 待压缩的文件或文件夹     * @param dstDir  压缩至该目录,保持原文件名,后缀改为zip     */    public static void zip(File srcFile, String dstDir) {        File file = new File(dstDir);        //需要判断该文件存在,且是文件夹        if (!file.exists() || !file.isDirectory()) file.mkdirs();        String dstPath = dstDir + File.separator + srcFile.getName() + ".zip";        FileOutputStream fos = null;        CheckedOutputStream cos = null;        ZipOutputStream zos = null;        try {            fos = new FileOutputStream(dstPath);            cos = new CheckedOutputStream(fos, new CRC32());            zos = new ZipOutputStream(cos);            zip(srcFile, zos, "");            zos.flush();        } catch (FileNotFoundException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        } finally {            try {                //关闭数据流的时候要先关闭外层,否则会报Stream Closed的错误                if (zos != null) zos.close();                if (cos != null) cos.close();                if (fos != null) fos.close();            } catch (IOException e) {                e.printStackTrace();            }        }    }    /**     * 解压     *     * @param srcFile 待解压的文件     * @param dstDir  解压到该目录,生成一个与原文件名相同的文件或文件夹     */    public static void unzip(File srcFile, String dstDir) {        File file = new File(dstDir);        //需要判断该文件存在,且是文件夹        if (!file.exists() || !file.isDirectory()) file.mkdirs();        ZipFile zipFile = null;        FileOutputStream fos = null;        InputStream is = null;        try {            //默认编码方式为UTF8            zipFile = new ZipFile(srcFile);            Enumeration<? extends ZipEntry> zipEntrys = zipFile.entries();            byte[] buffer = new byte[BUFF_SIZE];            int len = 0;            while (zipEntrys.hasMoreElements()) {                ZipEntry zipEntry = zipEntrys.nextElement();                String fileName = dstDir + File.separator + zipEntry.getName();                File tmpFile = new File(fileName);                File parent = tmpFile.getParentFile();                if (!parent.exists()) parent.mkdirs();                if (zipEntry.isDirectory()) {                    if (!tmpFile.exists()) tmpFile.mkdirs();                } else {                    fos = new FileOutputStream(tmpFile);                    is = zipFile.getInputStream(zipEntry);                    while ((len = is.read(buffer)) != -1) {                        fos.write(buffer, 0, len);                    }                    is.close();                    is = null;                    fos.flush();                    fos.close();                    fos = null;                }            }        } catch (IOException e) {            e.printStackTrace();        } finally {            try {                if (zipFile != null) zipFile.close();                if (is != null) is.close();                if (fos != null) fos.close();            } catch (IOException e) {                e.printStackTrace();            }        }    }    /**     * tar打包,GZip压缩     *     * @param file    待压缩的文件或文件夹     * @param taos    压缩流     * @param baseDir 相对压缩文件的相对路径     */    private static void tarGZip(File file, TarArchiveOutputStream taos, String baseDir) {        if (file.isDirectory()) {            File[] files = file.listFiles();            for (File f : files) {                tarGZip(f, taos, baseDir + file.getName() + File.separator);            }        } else {            byte[] buffer = new byte[BUFF_SIZE];            int len = 0;            FileInputStream fis = null;            TarArchiveEntry tarArchiveEntry = null;            try {                fis = new FileInputStream(file);                tarArchiveEntry = new TarArchiveEntry(file.getName());                tarArchiveEntry.setSize(file.length());                taos.putArchiveEntry(tarArchiveEntry);                while ((len = fis.read(buffer)) != -1) {                    taos.write(buffer, 0, len);                }                taos.flush();            } catch (FileNotFoundException e) {                e.printStackTrace();            } catch (IOException e) {                e.printStackTrace();            } finally {                try {                    if (fis != null) fis.close();                    if (tarArchiveEntry != null) taos.closeArchiveEntry();                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }    /**     * tar打包,GZip压缩     *     * @param srcFile 待压缩的文件或文件夹     * @param dstDir  压缩至该目录,保持原文件名,后缀改为zip     */    public static void tarGZip(File srcFile, String dstDir) {        File file = new File(dstDir);        //需要判断该文件存在,且是文件夹        if (!file.exists() || !file.isDirectory()) file.mkdirs();        //先打包成tar格式        String dstTarPath = dstDir + File.separator + srcFile.getName() + ".tar";        String dstPath = dstTarPath + ".gz";        FileOutputStream fos = null;        TarArchiveOutputStream taos = null;        try {            fos = new FileOutputStream(dstTarPath);            taos = new TarArchiveOutputStream(fos);            tarGZip(srcFile, taos, "");            taos.flush();        } catch (FileNotFoundException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        } finally {            try {                //关闭数据流的时候要先关闭外层,否则会报Stream Closed的错误                if (taos != null) taos.close();                if (fos != null) fos.close();            } catch (IOException e) {                e.printStackTrace();            }        }        File tarFile = new File(dstTarPath);        fos = null;        GZIPOutputStream gzip = null;        FileInputStream fis = null;        try {            //再压缩成gz格式            fos = new FileOutputStream(dstPath);            gzip = new GZIPOutputStream(fos);            fis = new FileInputStream(tarFile);            int len = 0;            byte[] buffer = new byte[BUFF_SIZE];            while ((len = fis.read(buffer)) != -1) {                gzip.write(buffer, 0, len);            }        } catch (FileNotFoundException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        } finally {            try {                if (fis != null) fis.close();                //关闭数据流的时候要先关闭外层,否则会报Stream Closed的错误                if (gzip != null) gzip.close();                if (fos != null) fos.close();            } catch (IOException e) {                e.printStackTrace();            }        }        //删除生成的tar临时文件        if (tarFile.exists()) tarFile.delete();    }    /**     * GZip解压,tar解包     *     * @param srcFile 待压缩的文件或文件夹     * @param dstDir  压缩至该目录,保持原文件名,后缀改为zip     */    public static void untarGZip(File srcFile, String dstDir) {        File file = new File(dstDir);        //需要判断该文件存在,且是文件夹        if (!file.exists() || !file.isDirectory()) file.mkdirs();        byte[] buffer = new byte[BUFF_SIZE];        FileInputStream fis = null;        GzipCompressorInputStream gcis = null;        TarArchiveInputStream tais = null;        try {            fis = new FileInputStream(srcFile);            gcis = new GzipCompressorInputStream(fis);            tais = new TarArchiveInputStream(gcis);            TarArchiveEntry tarArchiveEntry;            int len = 0;            while ((tarArchiveEntry = tais.getNextTarEntry()) != null) {                File f = new File(dstDir + File.separator + tarArchiveEntry.getName());                if (tarArchiveEntry.isDirectory()) f.mkdirs();                else {                    File parent = f.getParentFile();                    if (!parent.exists()) parent.mkdirs();                    FileOutputStream fos = new FileOutputStream(f);                    while ((len = tais.read(buffer)) != -1) {                        fos.write(buffer, 0, len);                    }                    fos.flush();                    fos.close();                }            }        } catch (FileNotFoundException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        } finally {            try {                if(fis != null) fis.close();                //关闭数据流的时候要先关闭外层,否则会报Stream Closed的错误                if(tais != null) tais.close();                if(gcis != null) gcis.close();            } catch (IOException e) {                e.printStackTrace();            }        }    }}

在module的build.gradle中添加如下依赖

dependencies {……//提供tar+gzip的打包方式(TarArchive和GZipCompress)//http://commons.apache.org/proper/commons-compress/download_compress.cgiimplementation 'org.apache.commons:commons-compress:1.18'}

JUnit 测试如下(注意:文件路径需要改成自己的)

@Test    public void compress() {        assertTrue(ZipOutputStream.class == getDelater());        byte[] data = randomBytes(65535);        byte[] zipData = CompressUtil.zip(data);        byte[] unzipData = CompressUtil.unzip(zipData);        assertArrayEquals(data, unzipData);        byte[] gzipData = CompressUtil.gzip(data);        byte[] ungzipData = CompressUtil.ungzip(gzipData);        assertArrayEquals(data, ungzipData);        String dir = "D:\\test";        String path = "D:\\test\\Test Folder";        String target = "D:\\test\\A\\B";        CompressUtil.zip(new File(path), dir);        CompressUtil.unzip(new File(path + ".zip"), target);        CompressUtil.tarGZip(new File(path), dir);        CompressUtil.untarGZip(new File(path + ".tar.gz"), target);    }

更多相关文章

  1. Error--->android工程导入找不到R文件
  2. 在AndroidManifest.xml文件中的android:windowSoftInputMode属性
  3. Gradle离线配置、.android、.AndroidStudio、.gradle、.m2缓存文
  4. Android 获取AndroidManifest.xml文件versionCode,versionName属
  5. Android客户端上传文件,C#服务端接收文件
  6. android 录音 Android 使用AudioRecord录音相关和音频文件的封装
  7. Android 实现文件(图片)上传
  8. android 读取raw文件下文件内容

随机推荐

  1. 通过WifiManager,DhcpInfo获取android IP
  2. Android(安卓)获取状态栏的高度
  3. Android启动优化
  4. linux基础教程--安装Android(安卓)SDK
  5. android之View属性
  6. cocos2d-x3.0beta版+NDK-r9b在android上
  7. android点击邮箱链接跳转发送
  8. Android(安卓)深入解析selector
  9. Android(安卓)ScrollView 判断到顶到底,和
  10. Android:开发常用的名令集锦