【Android】Android开发文件压缩与解压

压缩文件或目录

 public static void zip(String src,String dest) throws IOException {
        //定义压缩输出流
        ZipOutputStream out = null;
        try {
            //传入源文件
            File fileOrDirectory= new File(src);
            File outFile= new File(dest);
            //传入压缩输出流
            //创建文件前几级目录
            if (!outFile.exists()){
                File parentfile=outFile.getParentFile();
                if (!parentfile.exists()){
                    parentfile.mkdirs();
                }
            }
            //可以通过createNewFile()函数这样创建一个空的文件,也可以通过文件流的使用创建
            out = new ZipOutputStream(new FileOutputStream(outFile));
            //判断是否是一个文件或目录
            //如果是文件则压缩
            if (fileOrDirectory.isFile()){
                zipFileOrDirectory(out,fileOrDirectory, "");
            } else {
                //否则列出目录中的所有文件递归进行压缩

                File[]entries = fileOrDirectory.listFiles();
                for (int i= 0; i < entries.length;i++) {
                    zipFileOrDirectory(out,entries[i],fileOrDirectory.getName()+"/");//传入最外层目录名

                }
            }
        }catch(IOException ex) {
            ex.printStackTrace();
        }finally{
            if (out!= null){
                try {
                    out.close();
                }catch(IOException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }

    private static void zipFileOrDirectory(ZipOutputStream out, File fileOrDirectory, String curPath)throws IOException {
        FileInputStream in = null;
        try {
            //判断是否为目录
            if (!fileOrDirectory.isDirectory()){
                byte[] buffer= new byte[4096];
                int bytes_read;
                in= new FileInputStream(fileOrDirectory);//读目录中的子项
                //归档压缩目录
                ZipEntry entry = new ZipEntry(curPath + fileOrDirectory.getName());//压缩到压缩目录中的文件名字
                //getName() 方法返回的路径名的名称序列的最后一个名字,这意味着表示此抽象路径名的文件或目录的名称被返回。
                //将压缩目录写到输出流中
                out.putNextEntry(entry);//out是带有最初传进的文件信息,一直添加子项归档目录信息
                while ((bytes_read= in.read(buffer))!= -1) {
                    out.write(buffer,0, bytes_read);
                }
                out.closeEntry();
            } else {
                //列出目录中的所有文件
                File[]entries = fileOrDirectory.listFiles();
                for (int i= 0; i < entries.length;i++) {
                    //递归压缩
                    zipFileOrDirectory(out,entries[i],curPath + fileOrDirectory.getName()+ "/");//第一次传入的curPath是空字符串
                }//目录没有后缀所以直接可以加"/"
            }
        }catch(IOException ex) {
            ex.printStackTrace();
        }finally{
            if (in!= null){
                try {
                    in.close();
                }catch(IOException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }

思路:
1.创建文件压缩输出流ZipOutputStream ,和文件读入流FileInputStream
2.Zipoutputstream绑定一个目标目录,用ZipEntry归档在目标目录中添加输出子项
ZipEntry entry = new ZipEntry(curPath + fileOrDirectory.getName());
out.putNextEntry(entry);
3.FileInputStream在每次读入时绑定需要读入的文件
压缩时putNextEntry()对应解压时的getNextEntry()

解压文件或目录##

 public static void UnZipFolder(String FILE_PATH, String outPath) throws Exception{
        File zipFile = new File(FILE_PATH);//FILE_PATH为压缩文件的路径
        ZipFile zf = new ZipFile(zipFile);
        for(Enumeration<?> entries = zf.entries(); entries.hasMoreElements();){//遍历压缩文件中的所有归档过的文件

            ZipEntry entry = ((ZipEntry)entries.nextElement());//默认为-1,next->下标0的位置
            InputStream is = zf.getInputStream(entry);
            String str = outPath + File.separator + entry.getName();
            str = new String(str.getBytes("8859_1"),"GB2312");//压缩文件的编码是8859_1,此处可将其转换成指定的编码
            File desFile = new File(str);//其中单执行new file并不会在存储中创建文件或文件夹
            if(!desFile.exists()){
                File fileParentDir = desFile.getParentFile();
                if(!fileParentDir.exists()){
                    fileParentDir.mkdirs();//多级目录同时创建  怕文件归档在很多级目录下,或者文件需要在很多级未创建目录下,mkdir不会创建父目录,mkdirs会
                }
                desFile.createNewFile();//如果没有父目录将创建失败
            }
            FileOutputStream out = new FileOutputStream(desFile);
            byte buffer[] = new byte[1024*1024];
            int readLength;
            while((readLength = is.read(buffer)) > 0){
                out.write(buffer, 0, readLength);
            }
            is.close();
            out.close();
        }
    }

思路:
1.创建ZipFile对象
2.通过entry找到对应压缩文件输入流
InputStream is = zf.getInputStream(entry);
3.输入输出

为了解决有时我们需要从解压完的目录中获得某个指定文件的要求

/*
* 搜索对应文件从某目录中
* */
//保存搜索到的文件
    static File file;
    public static File findFile(File fileorfolder,String requestFile){
        file=null;//重置标识搜索文件的file为空
        searchFile(fileorfolder,requestFile);
        return file;
    }
    private static void searchFile(File fileorfolder,String requestFile){
        //是目录
        if(fileorfolder.isDirectory()){

            File[] entries=fileorfolder.listFiles();
            for(File enrtyfile:entries){
                searchFile(enrtyfile,requestFile);
            }
            //是文件
        }else {
            //是传入文件名对应文件
            if (fileorfolder.getName().equals(requestFile)){//equals是比较字符串值是否相等
                file=fileorfolder;
            }
        }
    }

##踩过的坑

1.压缩目录后解压,最外层目录丢失 例:/360/3/1(目录)2(目录) 压缩解压完/360消失,只剩/3 解决:归档代码出错,没有把归档信息带上最外层目录
2.(No such file or directory)异常,输出时在new file的file路径不存在(存在多级未创建目录) 解决:
(1).desFile.createNewFile();
(2).FileOutputStream out = new FileOutputStream(desFile);
(1).(2)两种方法都会创建文件,但如果没有父目录将创建失败,父目录可通过mkdirs创建,将递归创建
if (!outFile.exists()){
File parentfile=outFile.getParentFile();
if (!parentfile.exists()){
parentfile.mkdirs();
} }

使用到的一些类

ZipOutputStream :DeflaterOutputStream的一个子类,把数据压缩成Zip文件格式。
  ZipInputStream :InflaterInputStream的一个子类,能解压缩Zip格式的数据
  ZipEntry 类:表示 ZIP 文件条目
  ZipFile 类:此类用于从 ZIP 文件读取条目

ps:

1.压缩时的ZipEntry 非常重要,是解压时取得的归档信息
2.文件夹就算改成有后缀并不影响是文件夹:example->example.jpg还是文件夹
3.可以通过createNewFile()函数这样创建一个空的文件,也可以通过文件流的使用创建
desFile.createNewFile();//如果没有父目录将创建失败
FileOutputStream out = new FileOutputStream(desFile);//如果没有父目录将创建失败,即No such file or directory

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值