一、前言
在开发的过程中,我们有时候会遇到提供数据下载的功能,当数据量较大的时候,可能需要分开几个文件,然后再在后台打包成ZIP压缩文件,传送到前台。之前博客中有提及过如何用Java实现添加到压缩文件中,当时只讨论了如何单个文件添加压缩文件,这篇文章将讨论多文件压缩的问题。
二、多文件压缩
@Test public void test() throws Exception{ // 被压缩文件 File file = new File("C:\\Users\\Administrator\\Desktop\\文件a.pdf"); File file2 = new File("C:\\Users\\Administrator\\Desktop\\文件b.pdf"); // 输出文件outputStream File outFile = new File("C:\\Users\\Administrator\\Desktop\\压缩文件.zip"); FileOutputStream outputStream = new FileOutputStream(outFile); ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); // 读取file文件 FileInputStream inputStream = new FileInputStream(file); byte[] bytes = new byte[inputStream.available()]; inputStream.read(bytes); ZipEntry zipEntry = new ZipEntry(file.getName()); zipOutputStream.putNextEntry(zipEntry); zipOutputStream.write(bytes); zipOutputStream.flush(); // 读取file2文件 inputStream = new FileInputStream(file2); bytes = new byte[inputStream.available()]; inputStream.read(bytes); zipEntry = new ZipEntry(file2.getName()); zipOutputStream.putNextEntry(zipEntry); zipOutputStream.write(bytes); zipOutputStream.flush(); // 关闭各种流 zipOutputStream.closeEntry(); inputStream.close(); zipOutputStream.close(); outputStream.close(); }
上述这段代码,可以实现两个文件添加到ZIP压缩文件中。这种面相过程的写法,在某种程度上符合人的思考逻辑与顺序。但这种写法代码的耦合性高,代码复用性差。不是像上述代码那样写死,而是需要到本地文件中去取,又或者从数据库中拿,还是用POI读取Excel的方式获取文件路径,都不太好处理。人为操作的依赖性强。
三、基于面相对象多文件添加ZIP文件
/** * 文件读取缓冲区大小 */ private static final int CACHE_SIZE = 1024; @Test public void test2() throws Exception{ // 获取文件列表 List<File> fileList = this.getFileList(); // 压缩到ZIP文件中 this.toZIP(fileList); } /** * 获取文件列表 * @return */ private List<File> getFileList(){ List<File> fileList = new ArrayList<>(); File file = new File("C:\\Users\\Administrator\\Desktop\\文件a.pdf"); File file2 = new File("C:\\Users\\Administrator\\Desktop\\文件b.pdf"); fileList.add(file); fileList.add(file2); return fileList; } /** * 压缩到ZIP文件中 * @param fileList * @throws Exception */ private void toZIP(List<File> fileList) throws Exception{ // 定义读取问价及读取数组 FileInputStream inputStream = null; byte[] bytes = null; // 输出文件outputStream File outFile = new File("C:\\Users\\Administrator\\Desktop\\压缩文件.zip"); FileOutputStream outputStream = new FileOutputStream(outFile); ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream); // 循环写入ZIP文件 for(File file : fileList){ // 定义实体 ZipEntry zipEntry = new ZipEntry(file.getName()); zipOutputStream.putNextEntry(zipEntry); // 将文件读到数组中 inputStream = new FileInputStream(file); // 整体读到内存(文件过大会内存溢出) //bytes = new byte[inputStream.available()]; //inputStream.read(bytes); //zipOutputStream.write(bytes); // 分批读写 bytes = new byte[CACHE_SIZE]; int len = 0; while((len = inputStream.read(bytes)) != -1){ zipOutputStream.write(bytes); } zipOutputStream.flush(); } // 关闭各种流 zipOutputStream.closeEntry(); inputStream.close(); zipOutputStream.close(); outputStream.close(); }
该断代码中,重新划分获取文件的模块,同时增加的循环逻辑,提高代码的复用。在之前的文章中和上面的代码中,都需全部数据获取到数组中,为何这里需要分批读取呢?当文件大的时候,这样可以方式内存溢出的问题。而且通常开发者的电脑配置(内存)会高于服务器的内存配置,在开发者的电脑没问题,不代表生产环境没有问题,还是推荐使用分批读取。
Reference:
ryelqy, Java实现添加压缩文件, https://www.cnblogs.com/ryelqy/p/10104167.html