Android zip STORE方式存储文件和文件夹

背景:这个主要是需要动态更新Android系统的开机动画。
bootanimation.zip不是压缩形式的,而是归档形式的zip包。
java zip包可以支持STORE(归档)方式,但是查到的代码基本都有问题,都没有达到我想要归档效果。现记录下解决之后的code,避免有相同需求的同学再次踩坑。

目录结构:
这里写图片描述

两个分别有png图片的文件夹和一个txt文本。

private void CreateZipFile(){
        String zipPath = "data/local/my.zip";
        File zipFile = new File(zipPath);
         if(zipFile.exists())
                zipFile.delete();

        //创建zip包
        try{
            ZipOutputStream zip = new ZipOutputStream(new FileOutputStream(zipPath));
                ZipOneItem(zip,new File("data/local/part0"),"");
                ZipOneItem(zip,new File("data/local/part1"),"");
                ZipOneItem(zip,new File("data/local/3.txt"),"");
            zip.close();
            Log.d(TAG, "CreateZipFile SUCCESS!!!");
        }catch(FileNotFoundException ex){
            Log.d(TAG, "CreateZipFile FileNotFoundException!!!");
            ex.printStackTrace();
        }catch(IOException e){
            Log.d(TAG, "CreateZipFile IOException!!!");
            e.printStackTrace();
        }
    }
//压缩一个文件或者目录
private void ZipOneItem(ZipOutputStream zip, File f,String base){
    zip.setMethod(ZipOutputStream.STORED);//这个其实可有可无,ZipOutputStream.STORED其实就是后边的ZipEntry.STORED
    Log.d(TAG, "ZipOneItem in,f="+f.getName()+",base="+base);

    try{
        if(f.isDirectory()){
            File[] files = f.listFiles();

            //如果是多级目录part0/0.png这种,zip会根据/前边的名字自行构建多级目录的,所以这里只考虑空文件的情况,多级目录在下边else部分基本就可以。
            if(files.length == 0){ //构造一个空文件夹
                ZipEntry entry = new ZipEntry(base);
                zip.putNextEntry(entry);
            }
            //多级目录情况这里可能有点问题,读者请自行修改赋值路径相关。
            base = base.length() == 0 ? f.getName() + "/" : base + "/";
            for(int i=0; i < files.length; i++){
                ZipOneItem(zip,files[i],base + files[i].getName());
            }
        }else{
            //创建一个压缩文件
            base = base.length() == 0 ? f.getName() : base;//如果只压缩一个文件,还是要给个文件名才行
            Log.d(TAG, "ZipOneItem base="+base);
            ZipEntry entry = new ZipEntry(base);

            //这里开始很重要
            entry.setMethod(ZipEntry.STORED);
            entry.setCompressedSize(f.length());
            entry.setSize(f.length());
            CRC32 crc = new CRC32();
            crc.update(getFileBytes(f));
            entry.setCrc(crc.getValue());
            //以上很重要

            zip.putNextEntry(entry);

            int bufferLen = 1024;
            int fLen = (int)f.length();
            if(fLen < bufferLen){ //因为是储存,所以文件大小不能变。当小于1024时,使用文本大小
                bufferLen = fLen;
            }

            byte[] buffer = new byte[bufferLen];
            FileInputStream fis = new FileInputStream(f);
            int size = 0; 
            while( (size = fis.read(buffer)) != -1){
                zip.write(buffer,0,size);//这个很重要。之前查到的基本都是zip.write(buffer),这个会报错CRC missmatch。大坑。。。
            }
            //zip.closeEntry();这个可以不要,下一次的putNextEntry或者上边的zip.close都会调用closeEntry()
            fis.close();
        }
    }catch(Exception e){
        e.printStackTrace();
        Log.d(TAG, "ZipOneItem ERROR");
    }
    Log.d(TAG, "ZipOneItem SUCCESS");
}
private static byte[] getFileBytes(File file) throws Exception {
        byte[] buffer;
        FileInputStream fis = new FileInputStream(file);
        ByteArrayOutputStream bos = new ByteArrayOutputStream(1024);  
        byte[] b = new byte[1024];  
        int n;  
        while ((n = fis.read(b)) != -1) {  
            bos.write(b, 0, n);  
        }  
        fis.close();  
        bos.close();  
        buffer = bos.toByteArray();
        return buffer;
}

这个功能只适用于我个人,其他功能只能作为参考,请慎用。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值