赞
踩
最近在做项目的时候接触到需要在app上对压缩文件进行加密,也就是像pc上压缩文件的时候添加密码一样,打开压缩文件需要输入密码才能访问里面的内容。起初我所做的项目本身就是二次开发,要在前人地基础上进行添加密码,之前是已经有了压缩文件的代码了,只不过是使用的官方的ZipOutputStream
和ZipEntry
结合使用压缩的,我查了下官方api好像没有提供加密的。
这时候我就找了zip4j这个库,但是我查询了下http://www.lingala.net/zip4j.html 官网使用方法,具体使用方法https://github.com/srikanth-lingala/zip4j Github上都写的很清楚,这里我就不说了。
当然使用方法都是以java平台为例,直接是访问的windows上的路径,对于android来说,现在都是使用的Uri的路径,而zip4j是使用File的路径,当然现在Android还是可以使用File内部存储进行操作访问的,但是对于外部存储,比如otg连接的U盘。
首先我们android使用的时候使用的编译器是Android studio,使用build.gradle
来导入库的,
官方给出的是:
Maven
<dependency>
<groupId>net.lingala.zip4j</groupId>
<artifactId>zip4j</artifactId>
<version>1.3.3</version>
</dependency>
当然我们as导入直接复制上面一段代码,然后在build.gradle
中直接粘贴就行了
直接会变成该有的导入方式。
导入完成重新加载下就可以使用了。
当然现在官网已经更新到2.6.x,我为什么要用1.3.x的原因
1.首先是新版对我现在的app不友好。
2.还有就是网上大部分的使用资料都是1.3.x的,时间有限也不能慢慢去研究新用法了,所以就近原则。
首先先看看我原先的代码
当然这是我项目的代码块,用于说明,我尽量讲解一下,不然我自己到时候看都不是很清楚,
首先
val packTarPath = String.format(BACKUP_INFO_PATH, backupDirectory)
val outputStream = UsbFileStreamFactory.createBufferedOutputStream(
checkExist(
usbDevices.getUsbFile(context),
packTarPath
)?.createFile(BACKUP_DATA_NAME)
)
这一块是在我创建的压缩文件要放的路径和检查路径是否存在并创建,BACKUP_DATA_NAME
是压缩包的文件名当然要带后缀名的,因为要提取文件流outputStream
(BufferedOutputStream),这里我要注意的地方就是我开始所说的,我这里的路径是Uri
不是File
路径,因为使用File
的路径在外部存储设备上进行创建zip包是拒绝访问的,当然我现在是Android10,所以这里是使用Uri来创建并获取文件流的。context.contentResolver.openOutputStream(自己的uri)
,至于获取外部存储的uri网上就大把了。
//创建ZIP
val outZip = ZipOutputStream(outputStream)
Utils.compress(pas, usbFile, outZip, usbFile?.name, true, it)
//完成和关闭
outZip.finish()
outZip.close()
outputStream?.close()
然后这里就开始创建zip文件了,这里使用的ZipOutputStream
是zip4j里面的而不是自带的那个,
Utils.compress(pas, usbFile, outZip, usbFile?.name, true, it)
开始压缩,大概看一下。
下面是主要部分:
/** * 递归压缩方法 * * @param sourceFile 源文件 * @param zos zip输出流 * @param name 压缩后的名称 * @param KeepDirStructure 是否保留原来的目录结构,true:保留目录结构; * false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败) * @throws Exception */ public static void compress(String pas,UsbFile sourceFile, ZipOutputStream zos, String name, boolean KeepDirStructure, ObservableEmitter<PackTarModel> it) throws Exception { byte[] buf = new byte[4 * 1024]; if (sourceFile.isFile()) { //设置加密 ZipParameters para = new ZipParameters(); // 压缩方式 para.setCompressionMethod(Zip4jConstants.COMP_DEFLATE); para.setFileNameInZip(name); para.setSourceExternalStream(true); // 压缩级别 para.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL); para.setEncryptFiles(true); para.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES); para.setAesKeyStrength(Zip4jConstants.AES_STRENGTH_256); para.setPassword(pas); // 向zip输出流中添加一个zip实体,构造器中name为zip实体的文件的名字 zos.putNextEntry(new File(name), para); it.onNext(new PackTarModel(sourceFile.getAbsolutePath(), 0)); // copy文件到zip输出流中 int len; InputStream in = sourceFile.getInputStream(); while ((len = in.read(buf)) != -1) { zos.write(buf, 0, len); } // Complete the entry zos.closeEntry(); in.close(); } else { UsbFile[] listFiles = sourceFile.listFiles(); if (listFiles == null || listFiles.length == 0) { // 需要保留原来的文件结构时,需要对空文件夹进行处理 if (KeepDirStructure) { // 空文件夹的处理 zos.putNextEntry(new File(name + "/"), new ZipParameters()); // 没有文件,不需要文件的copy zos.closeEntry(); } } else { for (UsbFile file : listFiles) { // 判断是否需要保留原来的文件结构 if (KeepDirStructure) { // 注意:file.getName()前面需要带上父文件夹的名字加一斜杠, // 不然最后压缩包中就不能保留原来的文件结构,即:所有文件都跑到压缩包根目录下了 compress(pas,file, zos, name + "/" + file.getName(), KeepDirStructure, it); } else { compress(pas,file, zos, file.getName(), KeepDirStructure, it); } } } } }
第一个参数是后面加的密码,在这里所用的ZipOutputStream
是zip4j里面的,这里的操作ZipParameters
就是为压缩文件设置条件,zos.putNextEntry(new File(name), para);
其实这里与自带的ZipOutputStream
的区别是,自带的参数是ZipEntry
这个对象就可以了,而zip4j的是是个File
对象和ZipParameters
就可以了,当然是为了加密才使用的,没有加密的需求用自带的也是可以的。ZipEntry和File
都放的是文件名,所以这个没啥好说的。后面就正常操作,判断文件路径和文件。
本文章也主要是对自己所遇到的难题,做记录和学习,对广大朋友有小小的帮助是最好的,或者有问题的地方提出来讨论下,小生不才,有问题还望指出。嘻嘻声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。