递归的使用不当 导致 压缩文件不能压缩二级目录
错误展示:
错误代码:
import java.io.*;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;/*** @author 何* @date 2019-08-13 15:06*/
public class MyZipUtil {public static void main(String[] args) throws IOException {testZip("D:\\zip\\", "D:\\zip\\test.zip", 0);}/**** @param srcFilesAbsoluteParentPath 需要被压缩的文件的绝对父路径 例: D:\\zip 压缩这个目录下所有的文件* @param targetZipFileAbsolutePath 需要压缩到指定的位置的绝对路径(含文件名) 例: D:\\zip\\test.zip 压缩文件就放在这个位置* @throws IOException*/public static void testZip(String srcFilesAbsoluteParentPath, String targetZipFileAbsolutePath, int depth)throws IOException{//列出此目录所有文件,遍历操作File parentPath = new File(srcFilesAbsoluteParentPath);File[] files = parentPath.listFiles();//创建一个Zip文件输出流ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(targetZipFileAbsolutePath));for (int i = 0; i < files.length; i++) {File currentFile = files[i];//如果是目录则递归调用此方法if(currentFile.isDirectory()){testZip(currentFile.getAbsolutePath()+"\\", targetZipFileAbsolutePath, depth+1);continue;}/*根据目录深度,拼接zip文件里面的各个深度的文件的层次结构比如 在外面相对路径是 dir1/dir2/test.txt ,这个时候的文件名test.txt是不可以直接拿来作为entry的名字的,应该根据深度,获取他们的父目录的名称 拼接为 dir1/dir2/test.txt这样子才能保证层次结构不乱*/StringBuilder entryName = new StringBuilder(files[i].getName());File tempFile = files[i];for (int j = 0; j < depth; j++) {tempFile = tempFile.getParentFile();entryName.insert(0, tempFile.getName() + "\\");}zos.putNextEntry(new ZipEntry(entryName.toString()));//根据此文件创建输入流,用于等下文件的复制FileInputStream fis = new FileInputStream(currentFile.getAbsolutePath());//文件复制byte[] bytes = new byte[1024];int readedInt = 0;while( (readedInt=fis.read(bytes, 0, bytes.length))!=-1){zos.write(bytes, 0, readedInt);}fis.close(); //流要关闭}zos.finish();zos.close();}}
执行前文件结构截图
执行后的压缩文件内部截图
发现压缩文件的时候,并没有把更深层次的文件压缩进去。
错误原因:
如图可以看到,每次递归调用自身的时候,输出流的引用都指向了的更新的对象。即“对象”被“重置”了。
大概文件夹目录的文件虽然被正常压缩进去了,可是被外围的递归方法中产生的新的输出流给 覆盖 了。所以这就是为什么没报错,却也没有将子目录里面的文件压缩进去的原因。(本来压缩了,由于递归方法内我将输出流重置的原因,他被冲洗掉了)
警惕:
慎用递归,在循环调用自身的时候,一定要想清楚,哪些是在变的,哪些是不在变的。像我这个例子就是没有注意到 这个压缩文件应该自始至终都是“一个输出流”才对
贴上改正后自己写的Zip格式非加密 压缩与解压缩的工具类
ZipUtils.java
package com.zmedu.sdk.utils;import org.junit.Test;import java.io.*;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;/*** @author 何* @date 2019-08-13 15:06*/
public class MyZipUtil {public static void main(String[] args) throws IOException {// testZip("D:\\zip\\", "D:\\zip\\test.zip", 0);testUnzip("D:\\students\\students.zip", "D:\\students\\");}/**** @param srcFilesAbsoluteParentPath 需要被压缩的文件的绝对父路径 例: D:\\zip 压缩这个目录下所有的文件* @param targetZipFileAbsolutePath 需要压缩到指定的位置的绝对路径(含文件名) 例: D:\\zip\\test.zip 压缩文件就放在这个位置* @throws IOException*/public static void testZip(String srcFilesAbsoluteParentPath, String targetZipFileAbsolutePath, int depth)throws IOException{//列出此目录所有文件,遍历操作File parentPath = new File(srcFilesAbsoluteParentPath);File[] files = parentPath.listFiles();//创建一个Zip文件输出流ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(targetZipFileAbsolutePath));for (int i = 0; i < files.length; i++) {File currentFile = files[i];//如果是目录则递归调用此方法if(currentFile.isDirectory()){testZip(currentFile.getAbsolutePath()+"\\", targetZipFileAbsolutePath, depth+1);continue;}/*根据目录深度,拼接zip文件里面的各个深度的文件的层次结构比如 在外面相对路径是 dir1/dir2/test.txt ,这个时候的文件名test.txt是不可以直接拿来作为entry的名字的,应该根据深度,获取他们的父目录的名称 拼接为 dir1/dir2/test.txt这样子才能保证层次结构不乱*/StringBuilder entryName = new StringBuilder(files[i].getName());File tempFile = files[i];for (int j = 0; j < depth; j++) {tempFile = tempFile.getParentFile();entryName.insert(0, tempFile.getName() + "\\");}zos.putNextEntry(new ZipEntry(entryName.toString()));//根据此文件创建输入流,用于等下文件的复制FileInputStream fis = new FileInputStream(currentFile.getAbsolutePath());//文件复制byte[] bytes = new byte[1024];int readedInt = 0;while( (readedInt=fis.read(bytes, 0, bytes.length))!=-1){zos.write(bytes, 0, readedInt);}fis.close(); //流要关闭}zos.finish();zos.close();}/*** 解压Zip格式的非加密压缩文件* 提示:可以解压子目录的文件到对应的结构下,即这个压缩文件的子目录下还有孙子目录,也能一并解压* 缺点:不能解压里面的zip文件* 思路:可将每个 .zip 后缀的文件作为一个ZipFile的实例对象,调用.size()方法,抛出* java.util.zip.ZipException: error in opening zip file* 上面异常的则表示这个是不能打开的压缩文件,或者压根就不是压缩文件* @param zipFileAbsolutePath 压缩文件的绝对路径* @param destinationAbusolutePath 解压目的地的绝对路径* @throws IOException*/public static void testUnzip(String zipFileAbsolutePath, String destinationAbusolutePath) throws IOException {//根据压缩文件创建一个文件输入流,再创建一个Zip的专门的输入流FileInputStream fis = new FileInputStream(zipFileAbsolutePath); //"D:\\test\\test.zip"ZipInputStream zis = new ZipInputStream(fis);//可以当成压缩文件里面的条目ZipEntry zipEntry = null;//遍历所有条目 ,本质上就是把他们全部给复制一份出来while((zipEntry = zis.getNextEntry())!=null){System.out.println("当前文件: " + zipEntry.getName() + ", 大小: " + zipEntry.getSize());
// ZipFile zipFile = new ZipFile("D:\\unzip\\FacePictures\\xxx\\Faces List.txt");
// System.out.println(zipFile.size());//如果是目录则建个目录,不用自己去深度遍历,zis.getNextEntry会自动获取本压缩文件下的所有文件if(zipEntry.isDirectory()){File file = new File(destinationAbusolutePath+zipEntry.getName());file.mkdirs();continue;}//创建一个输出流,文件输出流或者字节数组输出流都行,二选一即可File beCreateedFile = new File(destinationAbusolutePath+zipEntry.getName());System.out.println("beCreateedFile: " + beCreateedFile);if (!(beCreateedFile.getParentFile().exists())) {beCreateedFile.getParentFile().mkdirs();}FileOutputStream fos = new FileOutputStream(beCreateedFile); //"D:\\test\\"ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();/* 第一种: 使用字节数组输出流的方式 *//*****************************************/byte[] bytes = new byte[1024]; //长度随意int readedInt = 0;while((readedInt = zis.read(bytes, 0, bytes.length)) != -1){fos.write(bytes, 0, readedInt);byteArrayOutputStream.write(bytes, 0, readedInt);}fos.close();/*****************************************//* 第二种: 使用字节数组输出流的方式 *//*****************************************/
// byte[] imgBytes = byteArrayOutputStream.toByteArray();
// fos = new FileOutputStream(destinationAbusolutePath+zipEntry.getName());
// fos.write(imgBytes);
// fos.close();/*****************************************/zis.closeEntry(); // 文档说要关闭,可是不关闭也可以,还是关闭把}//流要记得关闭!zis.close();fis.close();}
}
递归的使用不当 导致 压缩文件不能压缩二级目录相关推荐
- pdf压缩文件怎么压缩最小
pdf压缩文件怎么压缩最小?pdf文件我们在职场中接触的是很多的,但有时候文件太大导致我们在文件打开和传输的时候速度很慢.为了解决这个问题.我们会将pdf文件进行压缩,pdf压缩文件怎么压缩最小呢? ...
- 电脑上怎么做pdf文件_PDF压缩文件怎么压缩最小?请收好这些PDF压缩方法
刚才想把手头上的一份PDF文件发给同事,直接拖进窗口就显示文件太大,超出了大小限制.还好我平时经常要处理PDF文件,这种情况下将PDF文件压缩一下就可以了.PDF文件怎么进行压缩呢?下面我就把常用的P ...
- linux 解压tar.jz,linux系统压缩文件和解压缩命令
linux系统压缩文件和解压缩命令 tar命令 解包:tar zxvf FileName.tar 打包:tar czvf FileName.tar DirName gz命令 解压1:gunzip Fi ...
- ppt压缩文件怎么压缩最小,ppt无损压缩
ppt压缩文件怎么压缩最小? 在工作中,我们经常需要制作PPT文件进行汇报和分享,但有时候这些文件太大了,会影响下载和分享的速度,从而影响到工作效率.为了解决这个问题,我们可以对PPT文件进行压缩,从 ...
- pdf压缩文件怎么压缩最小,pdf大小超过上传大小不能上传怎么压缩?
pdf压缩文件怎么压缩最小?pdf是日常办公中比较常见的一种文件格式,但是有时候pdf文件的容量会比较大,上传到某些平台会有限制,那么我们就需要压缩pdf文件,但是有时候压缩处理会模糊,今天我给大家介 ...
- ppt压缩文件怎么压缩最小?
ppt压缩文件怎么压缩最小?ppt的全称是PowerPoint ,又叫幻灯片,是目前使用比较广泛的文件格式之一,会议报告文件或者自己的工作汇报等都是采用这种文件格式.ppt采用图文并茂的方式进行呈现, ...
- 电脑rar文件打开方式_怎么压缩文件,如何压缩文件?压缩软件哪个好?
超过10万人正在关注 赶快来关注吧,这里有你想找的热点资讯,这里有你想要的各种资料,还有海量的资源,还在等什么.快来关注,大佬带你开车. 在用电脑储存或者下载东西的时候,我们经常会遇到压缩的文件,或者 ...
- PDF压缩文件怎么压缩?两分钟让你学会三种方法
我们在传输PDF文件的时候,偶尔会因为文件过大,导致传输速度过长,甚至有时会提示,超出可传输的文件大小.这种时候就需要我们减小PDF文件的体积了,那有什么办法可以既保证文件内容质量,又可以减小文件体积 ...
- python压缩文件不带根路径_python 压缩文件(解决压缩路径问题)
#压缩文件 def Zip_files(): datapath = filepath # 证据路径 file_newname = datapath + '.zip' # 压缩文件的名字 log.deb ...
最新文章
- 处理您的请求时发生错误(Web Dynpro ABAP)
- ubuntu apache php mysql phpmyadmin_Ubuntu下Apache+PHP+MySQL+phpMyAdmin的快速安装步骤
- php安装编译时 configure: error: Cannot find OpenSSL's evp.h
- c++ winpcap开发(4)
- 解决VS2017引用报错问题
- Android java传递int类型数组给C
- 刷新按钮_不能忍:用户求微软为Win10 Wi-Fi窗口添加刷新按钮
- Firefox的缓存问题
- Ubuntu14 添加程序启动
- ROS Learning-008 beginner_Tutorials ROS话题
- Framework4.5,vs下系统自动生成的C++ win32应用程序的详细解释
- python谐音梗_谐音梗生成器
- 论基于构件的软件开发
- mysql错误:Table XXX is marked as crashed and should be repaire
- 想要成为大牛应该做到以下几点
- mat1 and mat2 shapes cannot be multiplied (3584x7 and 512x4096)
- 轻薄旗舰投影两大阵营大眼橙X7D Pro和极米Z7X,谁才是真正的高性价比之选?
- UEFI启动模式下, 双硬盘安装UBuntu16.04与Win10双系统
- 三种方法求最大公约数(C语言版)
- 电脑插了两根内存条只读出来一根,另一条是为硬件保留的内存空间
热门文章
- iPhone 14 Pro系列传出好消息,有望实现8GB内存自由
- 高通第一财季营收107亿美元 净利润超过30亿美元
- “真还传”即将完结?锤子科技撤回全部破产申请 罗永浩称年后回归科技界
- 何小鹏:雷军造车是我“怂恿的” 我一直建议小米要造车
- 知乎回应月饼问题:忽略了麦芽糖或致部分人不耐受,召回所有月饼
- 妙啊,小米11保护壳先小米11一步上市了...
- 北京一Model 3失控冲向公交站台,特斯拉调查后回应......
- 前华为、魅族CMO加盟小米,雷军这样评价
- iPad有望带来全面鼠标支持 大幅提升游戏体验
- 16999元!华为Mate X 5G折叠屏手机正式发布:不愧是限量款