服务器之家

服务器之家 > 正文

Java实现将文件或者文件夹压缩成zip的详细代码

时间:2022-03-08 00:46     来源/作者:zeng1994

最近碰到个需要下载zip压缩包的需求,于是我在网上找了下别人写好的zip工具类。但找了好多篇博客,总是发现有bug。因此就自己来写了个工具类。
        这个工具类的功能为:
(1)可以压缩文件,也可以压缩文件夹
(2)同时支持压缩多级文件夹,工具内部做了递归处理
(3)碰到空的文件夹,也可以压缩
(4)可以选择是否保留原来的目录结构,如果不保留,所有文件跑压缩包根目录去了,且空文件夹直接舍弃。注意:如果不保留文件原来目录结构,在碰到文件名相同的文件时,会压缩失败。
(5)代码中提供了2个压缩文件的方法,一个的输入参数为文件夹路径,一个为文件列表,可根据实际需求选择方法。

下面直接上代码

一、代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
package com.tax.core.util;
 
import java.io.File;
 
import java.io.FileInputStream;
 
import java.io.FileOutputStream;
 
import java.io.IOException;
 
import java.io.OutputStream;
 
import java.util.ArrayList;
 
import java.util.List;
 
import java.util.zip.ZipEntry;
 
import java.util.zip.ZipOutputStream;
 
/**
 
 * ZipUtils
 
 * @author  ZENG.XIAO.YAN
 
 * @date    2017年11月19日 下午7:16:08
 
 * @version v1.0
 
 */
 
public class ZipUtils {
 
    
 
    private static final int  BUFFER_SIZE = 2 * 1024;
 
    /**
 
     * 压缩成ZIP 方法1
 
     * @param srcDir 压缩文件夹路径
 
     * @param out    压缩文件输出流
 
     * @param KeepDirStructure  是否保留原来的目录结构,true:保留目录结构;
 
     *                          false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
 
     * @throws RuntimeException 压缩失败会抛出运行时异常
 
     */
 
    public static void toZip(String srcDir, OutputStream out, boolean KeepDirStructure)
           throws RuntimeException{
 
        
 
        long start = System.currentTimeMillis();
 
        ZipOutputStream zos = null ;
 
        try {
 
            zos = new ZipOutputStream(out);
 
            File sourceFile = new File(srcDir);
 
            compress(sourceFile,zos,sourceFile.getName(),KeepDirStructure);
 
            long end = System.currentTimeMillis();
 
            System.out.println("压缩完成,耗时:" + (end - start) +" ms");
 
        } catch (Exception e) {
 
            throw new RuntimeException("zip error from ZipUtils",e);
 
        }finally{
 
            if(zos != null){
 
                try {
 
                    zos.close();
 
                } catch (IOException e) {
 
                    e.printStackTrace();
 
                }
 
            }
 
        }
 
        
 
    }
 
    
 
    /**
 
     * 压缩成ZIP 方法2
 
     * @param srcFiles 需要压缩的文件列表
 
     * @param out           压缩文件输出流
 
     * @throws RuntimeException 压缩失败会抛出运行时异常
 
     */
 
    public static void toZip(List<File> srcFiles , OutputStream out)throws RuntimeException {
 
        long start = System.currentTimeMillis();
 
        ZipOutputStream zos = null ;
 
        try {
 
            zos = new ZipOutputStream(out);
 
            for (File srcFile : srcFiles) {
 
                byte[] buf = new byte[BUFFER_SIZE];
 
                zos.putNextEntry(new ZipEntry(srcFile.getName()));
 
                int len;
 
                FileInputStream in = new FileInputStream(srcFile);
 
                while ((len = in.read(buf)) != -1){
 
                    zos.write(buf, 0, len);
 
                }
 
                zos.closeEntry();
 
                in.close();
 
            }
 
            long end = System.currentTimeMillis();
 
            System.out.println("压缩完成,耗时:" + (end - start) +" ms");
 
        } catch (Exception e) {
 
            throw new RuntimeException("zip error from ZipUtils",e);
 
        }finally{
 
            if(zos != null){
 
                try {
 
                    zos.close();
 
                } catch (IOException e) {
 
                    e.printStackTrace();
 
                }
 
            }
 
        }
 
    }
 
    
 
    
 
    /**
 
     * 递归压缩方法
 
     * @param sourceFile 源文件
 
     * @param zos        zip输出流
 
     * @param name       压缩后的名称
 
     * @param KeepDirStructure  是否保留原来的目录结构,true:保留目录结构;
 
     *                          false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
 
     * @throws Exception
 
     */
 
    private static void compress(File sourceFile, ZipOutputStream zos, String name,
 
            boolean KeepDirStructure) throws Exception{
 
        byte[] buf = new byte[BUFFER_SIZE];
 
        if(sourceFile.isFile()){
 
            // 向zip输出流中添加一个zip实体,构造器中name为zip实体的文件的名字
 
            zos.putNextEntry(new ZipEntry(name));
 
            // copy文件到zip输出流中
 
            int len;
 
            FileInputStream in = new FileInputStream(sourceFile);
 
            while ((len = in.read(buf)) != -1){
 
                zos.write(buf, 0, len);
 
            }
 
            // Complete the entry
 
            zos.closeEntry();
 
            in.close();
 
        } else {
 
            File[] listFiles = sourceFile.listFiles();
 
            if(listFiles == null || listFiles.length == 0){
 
                // 需要保留原来的文件结构时,需要对空文件夹进行处理
 
                if(KeepDirStructure){
 
                    // 空文件夹的处理
 
                    zos.putNextEntry(new ZipEntry(name + "/"));
 
                    // 没有文件,不需要文件的copy
 
                    zos.closeEntry();
 
                }
 
                
 
            }else {
 
                for (File file : listFiles) {
 
                    // 判断是否需要保留原来的文件结构
 
                    if (KeepDirStructure) {
 
                        // 注意:file.getName()前面需要带上父文件夹的名字加一斜杠,
 
                        // 不然最后压缩包中就不能保留原来的文件结构,即:所有文件都跑到压缩包根目录下了
 
                        compress(file, zos, name + "/" + file.getName(),KeepDirStructure);
 
                    } else {
 
                        compress(file, zos, file.getName(),KeepDirStructure);
 
                    }
 
                    
 
                }
 
            }
 
        }
 
    }
 
    public static void main(String[] args) throws Exception {
 
        /** 测试压缩方法1  */
 
        FileOutputStream fos1 = new FileOutputStream(new File("c:/mytest01.zip"));
 
        ZipUtils.toZip("D:/log", fos1,true);
 
        /** 测试压缩方法2  */
 
        List<File> fileList = new ArrayList<>();
 
        fileList.add(new File("D:/Java/jdk1.7.0_45_64bit/bin/jar.exe"));
 
        fileList.add(new File("D:/Java/jdk1.7.0_45_64bit/bin/java.exe"));
 
        FileOutputStream fos2 = new FileOutputStream(new File("c:/mytest02.zip"));
 
        ZipUtils.toZip(fileList, fos2);
 
    }
 
}

二、注意事项

写该工具类时,有些注意事项说一下:
        (1)支持选择是否保留原来的文件目录结构,如果不保留,那么空文件夹直接不用处理。
        (1)碰到空文件夹时,如果需要保留目录结构,则直接添加个ZipEntry就可以了,不过就是这个entry的名字后面需要带上一斜杠(/)表示这个是目录。
        (2)递归时,不需要把zip输出流关闭,zip输出流的关闭应该是在调用完递归方法后面关闭
        (3)递归时,如果是个文件夹且需要保留目录结构,那么在调用方法压缩他的子文件时,需要把文件夹的名字加一斜杠给添加到子文件名字前面,这样压缩后才有多级目录。

三、如何在javaWeb项目中使用该工具类

    这个工具类在web项目中的使用场景就是多文件下载,我就简单说个下载多个excel表格的案例吧。
    代码中的步骤为:
        (1)创建一个临时文件夹
        (2)将要下载的文件生成至该临时文件夹内
        (3)当所有文件生成完后,获取HttpServletResponse获取设置下载的header
        (4)调用工具类的方法,传入上面生成的临时文件夹路径及response获取的输出流;这样就下载出来zip包了
        (5)递归删除掉上面生成的临时文件夹和文件

    下面为一个示例代码的代码片段,不是完整代码,简单看一下代码中的步骤

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
if(userList.size() > 0){
 
        /** 下面为下载zip压缩包相关流程 */
 
        HttpServletRequest request = ServletActionContext.getRequest();
 
        FileWriter writer;
 
        /** 1.创建临时文件夹  */
 
        String rootPath = request.getSession().getServletContext().getRealPath("/");
 
        File temDir = new File(rootPath + "/" + UUID.randomUUID().toString().replaceAll("-", ""));
 
        if(!temDir.exists()){
 
            temDir.mkdirs();
 
        }
 
        /** 2.生成需要下载的文件,存放在临时文件夹内 */
 
        // 这里我们直接来10个内容相同的文件为例,但这个10个文件名不可以相同
 
        for (int i = 0; i < 10; i++) {
 
            dataMap.put("userList", userList);
 
            Map<String, String> endMap = new HashMap<>();
 
            endMap.put("user", "老王");
 
            endMap.put("time", "2017-10-10 10:50:55");
 
            dataMap.put("endMap", endMap);
 
            Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);
 
            cfg.setServletContextForTemplateLoading(ServletActionContext.getServletContext(), "/ftl");
 
            Template template = cfg.getTemplate("exportExcel.ftl");
 
            writer = new FileWriter(temDir.getPath()+"/excel"+ i +".xls");
 
            template.process(dataMap, writer);
 
            writer.flush();
 
            writer.close();
 
        }
 
        
 
        /** 3.设置response的header */
 
        HttpServletResponse response = ServletActionContext.getResponse();
 
        response.setContentType("application/zip");
 
        response.setHeader("Content-Disposition", "attachment; filename=excel.zip"); 
 
        /** 4.调用工具类,下载zip压缩包 */
 
        // 这里我们不需要保留目录结构
 
        ZipUtils.toZip(temDir.getPath(), response.getOutputStream(),false);
 
   /** 5.删除临时文件和文件夹 */
 
        // 这里我没写递归,直接就这样删除了
 
        File[] listFiles = temDir.listFiles();
 
        for (int i = 0; i < listFiles.length; i++) {
 
            listFiles[i].delete();
 
        }
 
        temDir.delete();
 
    }

到此这篇关于Java实现将文件或者文件夹压缩成zip的文章就介绍到这了,更多相关Java实现将文件或者文件夹压缩成zip内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://www.cnblogs.com/zeng1994/p/7862288.html

标签:

相关文章

热门资讯

2022年最旺的微信头像大全 微信头像2022年最新版图片
2022年最旺的微信头像大全 微信头像2022年最新版图片 2022-01-10
蜘蛛侠3英雄无归3正片免费播放 蜘蛛侠3在线观看免费高清完整
蜘蛛侠3英雄无归3正片免费播放 蜘蛛侠3在线观看免费高清完整 2021-08-24
背刺什么意思 网络词语背刺是什么梗
背刺什么意思 网络词语背刺是什么梗 2020-05-22
yue是什么意思 网络流行语yue了是什么梗
yue是什么意思 网络流行语yue了是什么梗 2020-10-11
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全 2019-12-26
返回顶部