Java压缩包(zip)【学习笔记】
前言
Java实现Zip压缩解压可以使用JDK的原生类java.util.zip,但是JDK 7 之前存在中文文件名乱码问题。
使用 ant.jar 的org.apache.tools.zip包,可以避免乱码问题。
使用专门的压缩解压第三方组件,如zip4j,zt-zip等,这种实现方式当然更强大,不过一般场景压缩解压就可以满足需求了。
本博客简单介绍java8下的zip压缩解压。
起步
- java8
开始
java的io包下运用了装饰模式,对结构不清晰的小伙伴可以先看下装饰模式,在尝试下看java的io包下的源码,来熟悉io操作。
大致设计思想:
装饰成InputStream/OutputStream | 装饰成BufferedStream | |
---|---|---|
File | FileInputStream(new File) | BufferedInputStream(new FileInputStream) |
FileOutputStream(new File) | BufferedOutputStream(new FileOutputStream) | |
Writer/Reader | BufferedReader/BufferedWriter | |
FileReader(new File) | BufferedReader(new FileReader) | |
FileWriter(new File) | BufferedWriter(new FileWriter) |
熟悉之后,让我们开始使用ZipInputStream和ZipOutputStream吧。
这里我们采用 策略模式 设计demo。
- demo地址
喜欢直接看项目的可以直接 >> demo-zip
- 代码目录结构
- 抽象压缩策略类
/**
* @author quaint
* @date 15 February 2020
* @since master
*/
public interface CompressionStrategy <T> {
/**
* 是否支持
* @param fileName 文件名称
* @return true
*/
boolean support(String fileName);
/**
* 提取策略
* @param inputStream 文件
* @return 数据
* @throws IOException io
*/
List<T> extract(InputStream inputStream) throws IOException;
/**
* 压缩策略
* @param dataList 数据
* @param os 输出流
* @throws IOException io
*/
void compression(List<T> dataList, OutputStream os) throws IOException;
}
- zip策略实现
/**
* @author quaint
* @date 15 February 2020
* @since master
*/
@Component
public class ZipImageStrategy implements CompressionStrategy<ImageDto> {
/**
* 传入文件类型
*/
private static final String ZIP_FORMAT = ".zip";
/**
* 目标类型
*/
private static final List<String> TARGET_TYPE = Arrays.asList(".png", ".jpeg", ".jpg", ".gif");
@Override
public boolean support(String fileName) {
if (StringUtils.isEmpty(fileName)) {
return false;
}
return fileName.endsWith(ZIP_FORMAT);
}
@Override
public List<ImageDto> extract(InputStream inputStream) throws IOException {
if (inputStream == null){
return null;
}
// 定义储存数据的list
List<ImageDto> dataList = new ArrayList<>();
// 把输入流 包装为 压缩流
ZipInputStream zis = new ZipInputStream(inputStream);
ZipEntry ze;
while ((ze = zis.getNextEntry()) != null) {
String name = ze.getName();
// 过滤掉 多余的文件/不是图片的文件
if (ze.isDirectory() || name == null || name.contains("__MACOSX") || name.contains(".DS_Store")
|| !TARGET_TYPE.contains(name.substring(name.lastIndexOf('.')))) {
continue;
}
// 添加图片到集合
ImageDto imageDto = new ImageDto();
imageDto.setFileName(name.substring(name.lastIndexOf(File.separator) + 1));
// 将文件转换为 byte 数组
ByteArrayOutputStream output = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int n;
while(-1 != (n = zis.read(buffer))) {
output.write(buffer, 0, n);
}
imageDto.setBytes(output.toByteArray());
dataList.add(imageDto);
}
zis.close();
return dataList;
}
@Override
public void compression(List<ImageDto> dataList, OutputStream os) throws IOException {
if (CollectionUtils.isEmpty(dataList) || os == null){
return;
}
// 把输出流包装为 压缩流
ZipOutputStream zos = new ZipOutputStream(os);
// 循环写压缩文件
for (ImageDto file : dataList) {
ZipEntry ze = new ZipEntry(file.getFileName());
zos.putNextEntry(ze);
zos.write(file.getBytes(),0,file.getBytes().length);
zos.closeEntry();
}
zos.close();
}
}
- 图片dto
/**
* 图片实体类,简单版
* @author quaint
* @date 15 February 2020
* @since master
*/
@Data
public class ImageDto {
/**
* 文件名称
*/
private String fileName;
/**
* 文件字节码
*/
private byte[] bytes;
}
- spi接口
/**
* @author quaint
* @date 11 February 2020
* @since master
*/
@RestController
@Slf4j
@Api(tags = {"zip测试demo","分类: 测试"})
public class ZipDemoSpi {
/**
* 单例 包含的对象也是单例, 方便测试, 先把解压的图片 暂时存在这里, 然后在压缩 提供web下载
* swagger 操作流程, -->先解压, -->在压缩
*/
private List<ImageDto> tempData;
@Autowired
List<CompressionStrategy<ImageDto>> compressionStrategies;
/**
* 解压web传来的zip
*/
@ApiOperation("解压web传来的zip")
@PostMapping("/web/unzip")
public String webUnzipDemo(@RequestParam("fileData") MultipartFile file){
// 选取解压策略
Optional<CompressionStrategy<ImageDto>> best = compressionStrategies.stream()
.filter(strategy -> strategy.support(file.getOriginalFilename())).findFirst();
// 如果支持该类型
if (best.isPresent()){
try {
List<ImageDto> extract = best.get().extract(file.getInputStream());
// 测试解压结果
extract.forEach(imageDto -> log.info("解压到一个图片-->"+imageDto.getFileName()));
tempData = new ArrayList<>();
tempData.addAll(extract);
} catch (IOException e) {
e.printStackTrace();
}
} else {
return "解压失败";
}
return "解压成功";
}
/**
* 解压local传来的zip
*/
@ApiOperation("解压local传来的zip")
@PostMapping("/local/unzip")
public String localUnzipDemo(){
// 获取当前项目文件夹的的zip文件
String filePath = System.getProperty("user.dir")+"/demo-zip/src/main/resources/image.zip";
String fileName = filePath.substring(filePath.lastIndexOf('/')+1);
Optional<CompressionStrategy<ImageDto>> best = compressionStrategies.stream()
.filter(strategy -> strategy.support(fileName)).findFirst();
if (best.isPresent()){
try {
InputStream inputStream = new FileInputStream(filePath);
List<ImageDto> extract = best.get().extract(inputStream);
// 测试解压结果
extract.forEach(imageDto -> log.info("解压到一个图片-->"+imageDto.getFileName()));
tempData = new ArrayList<>();
tempData.addAll(extract);
} catch (IOException e) {
e.printStackTrace();
return "本地文件解压异常";
}
}
return "本地文件解压成功";
}
/**
* 压缩图片到web
*/
@ApiOperation("压缩图片到web")
@PostMapping("/web/compression")
public String webCompressionDemo(HttpServletResponse response){
Optional<CompressionStrategy<ImageDto>> best = compressionStrategies.stream()
.filter(strategy -> strategy.support("demo.zip")).findFirst();
if (best.isPresent()){
try {
// 压缩到指定输出流
best.get().compression(tempData,response.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
return "web文件压缩异常";
}
}
return "web文件压缩成功";
}
/**
* 压缩图片到local
*/
@ApiOperation("压缩图片到local")
@PostMapping("/local/compression")
public String localCompressionDemo(){
// 获取当前项目文件夹的的zip文件
String filePath = System.getProperty("user.dir")+"/demo-zip/src/main/resources/imageTest.zip";
String fileName = filePath.substring(filePath.lastIndexOf('/')+1);
try {
OutputStream os = new FileOutputStream(new File(filePath));
Optional<CompressionStrategy<ImageDto>> best = compressionStrategies.stream()
.filter(strategy -> strategy.support(fileName)).findFirst();
// 压缩到指定输出流
if (best.isPresent()){
best.get().compression(tempData,os);
}
} catch (IOException e) {
e.printStackTrace();
return "压缩图片到本地异常";
}
return "压缩图片到本地成功";
}
}
致谢
一直往前走,别往后看。顺其自然,内心就会逐渐清朗,时光越老,人心越淡。常怀宽容感激之心,宽容那就是一种美德是一种智慧,海纳百川是多么广阔,感激你的朋友,是他们给了你帮助;感激你的敌人,是他们是让你变的坚强。感谢你的阅读,你努力的样子很可爱呀。
Java压缩包(zip)【学习笔记】的更多相关文章
- 《深入理解Java虚拟机》学习笔记
<深入理解Java虚拟机>学习笔记 一.走近Java JDK(Java Development Kit):包含Java程序设计语言,Java虚拟机,JavaAPI,是用于支持 Java 程 ...
- JAVA GUI编程学习笔记目录
2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...
- Java多线程技术学习笔记(二)
目录: 线程间的通信示例 等待唤醒机制 等待唤醒机制的优化 线程间通信经典问题:多生产者多消费者问题 多生产多消费问题的解决 JDK1.5之后的新加锁方式 多生产多消费问题的新解决办法 sleep和w ...
- Java安全防御学习笔记V1.0
Java安全防御学习笔记V1.0http://www.docin.com/p-766808938.html
- java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)
java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessCo ...
- java之jvm学习笔记三(Class文件检验器)
java之jvm学习笔记三(Class文件检验器) 前面的学习我们知道了class文件被类装载器所装载,但是在装载class文件之前或之后,class文件实际上还需要被校验,这就是今天的学习主题,cl ...
- java之jvm学习笔记五(实践写自己的类装载器)
java之jvm学习笔记五(实践写自己的类装载器) 课程源码:http://download.csdn.net/detail/yfqnihao/4866501 前面第三和第四节我们一直在强调一句话,类 ...
- java之jvm学习笔记四(安全管理器)
java之jvm学习笔记四(安全管理器) 前面已经简述了java的安全模型的两个组成部分(类装载器,class文件校验器),接下来学习的是java安全模型的另外一个重要组成部分安全管理器. 安全管理器 ...
- java之jvm学习笔记二(类装载器的体系结构)
java的class只在需要的时候才内转载入内存,并由java虚拟机的执行引擎来执行,而执行引擎从总的来说主要的执行方式分为四种, 第一种,一次性解释代码,也就是当字节码转载到内存后,每次需要都会重新 ...
- java之jvm学习笔记十三(jvm基本结构)
java之jvm学习笔记十三(jvm基本结构) 这一节,主要来学习jvm的基本结构,也就是概述.说是概述,内容很多,而且概念量也很大,不过关于概念方面,你不用担心,我完全有信心,让概念在你的脑子里变成 ...
随机推荐
- jS Ajax 上传文件报错"Uncaught TypeError: Illegal invocation"
使用jquery ajax异步提交文件的时候报Uncaught TypeError :Illegal invocation错误,报错信息如图: 错误原因: jQuery Ajax 上传文件处理方式,使 ...
- [C++]最小生成树
1. 最小生成树定义 树是指没有环路的图,生成树就是指一个图上面删除一些边,使它没有环路. 最小生成树就是指生成树中边权之和最小的那一种. 上图的最小生成树就是这样: 2. Prim 算法 2.1. ...
- Spring-cloud微服务实战【三】:eureka注册中心(中)
回忆一下,在上一篇文章中,我们创建了两个springboot项目,并且在consumer项目中通过restTemplate进行HTTP通信,成功访问到了producer提供的接口,思考一下这样的实 ...
- 关于SDWebImage的一点小坑
做项目遇到一个问题,是用sd加载图片,明明本地有图片,使用sd的内部方法也可以拿到那些个图片,但是就是加载缓慢,如果网络还行,网络加载图片都比加载本地图片快.而使用[[SDImageCache ...
- 死磕面试 - Dubbo基础知识37问(必须掌握)
作为一个JAVA工程师,出去项目拿20k薪资以上,dubbo绝对是面试必问的,即使你对dubbo在项目架构上的作用不了解,但dubbo的基础知识也必须掌握. 整理分享一些面试中常会被问到的dubbo基 ...
- MySQL8.0.19安装
官网下载安装包:mysql-8.0.19-linux-glibc2.12-x86_64.tar.xz 安装环境:CentOS Linux release 7.5.1804 (Core) 解压安装包: ...
- Java入门 - 语言基础 - 04.对象和类
原文地址:http://www.work100.net/training/java-object-class.html 更多教程:光束云 - 免费课程 对象和类 序号 文内章节 视频 1 概述 2 J ...
- Dijkstra求解单源最短路径
Dijkstra(迪杰斯特拉)单源最短路径算法 Dijkstra思想 Dijkstra是一种求单源最短路径的算法. Dijkstra仅仅适用于非负权图,但是时间复杂度十分优秀. Dijkstra算法主 ...
- 在eclipse里用jdbc连接MySQL
进入MySQL控制台, 输入密码, 新建数据库test1并给用户授权,用户名“jaovo”, 创建表,id主键自增, 下载jdbc驱动包(jar文件) 把它放进tomcat的安装目录lib文件夹下(我 ...
- C#数字图像处理(十四)击中击不中变换 (Hit-miss)
击中击不中变换定义 击中击不中变换(HMT)需要两个结构元素B1和B2,合成一个结构元素对B=(B1,B2) 一个用于探测图像内部,作为击中部分;另一个用于探测图像外部,作为击不中部分.显然,B1和B ...