最近在工作中需要在浏览器中一次性下载多个文件,于是想到了使用压缩的功能。百度了一下,发现很多博客都是照抄照搬的,于是自己写了这么一个工具类,实现文件的压缩和解压。
代码:
/*** 使用方法:* byte[] bytes = ZipUtil.createZipObject().addFile(fileBytes, "hello.xls").create();** 需要添加多个文件就调用多次addFile,最后调用create生成字节数组即可**/
public class ZipUtil {private ZipUtil() {throw new RuntimeException("Illegal operation");}// 压缩文件public static ZipObject createZipObject() {return new ZipObject();}// 解压文件,参数是压缩文件字节数组public static UnZipObject createUnZipObject(byte[] bytes) {if (bytes==null || bytes.length==0) {throw new IllegalArgumentException("bytes is null");}return new UnZipObject(bytes);}public static class ZipObject {// 工具流private ZipOutputStream zos;// 使用带有缓冲功能的文件流存储文件private ByteArrayOutputStream bos;private ZipObject() {bos = new ByteArrayOutputStream();// 文件数据流实际存储在了boszos = new ZipOutputStream(bos);}/*** 添加一个文件到压缩包中* @param fileBytes 文件的字节数组* @param fileName 文件名,带文件类型的,比如:hello.xlsx* @return*/public ZipObject addFile(byte[] fileBytes, String fileName) {try {// 可以理解一个ZipEntry就表示压缩包里面的一个文件ZipEntry zipEntry = new ZipEntry(fileName);zos.putNextEntry(zipEntry);zos.write(fileBytes, 0, fileBytes.length);} catch (IOException e) {if (bos!=null) {try {bos.close();} catch (IOException ee){}}if (zos!=null) {try {zos.close();} catch (IOException ee){}}}return this;}/*** 生成压缩包的字节数组* @return*/public byte[] create() {byte[] bytes = null;try {// 将数据写到ByteArrayOutputStream中zos.finish();bytes = bos.toByteArray();bos.flush();zos.flush();} catch (IOException e) {e.printStackTrace();} finally {if (bos!=null) {try {bos.close();} catch (IOException e){}}if (zos!=null) {try {zos.close();} catch (IOException e){}}}return bytes;}}public static class UnZipObject {// 工具流private ZipInputStream zis;// 使用带有缓冲功能的文件流存储文件private ByteArrayInputStream bis;private int size;private UnZipObject(byte[] bytes) {size = bytes.length;bis = new ByteArrayInputStream(bytes);// 文件数据流实际存储在了boszis = new ZipInputStream(bis);}/*** 获取压缩包里面的文件,一个ZipEntry表示一个文件* @return*/public List<ZipEntry> getEntrys() {List<ZipEntry> list = new ArrayList<>();try {ZipEntry nextEntry = zis.getNextEntry();// 一个个循环读取压缩文件中的内容,放进bytes数组中while (nextEntry!=null) {byte[] bytes = new byte[size];zis.read(bytes);nextEntry.setExtra(bytes);list.add(nextEntry);nextEntry = zis.getNextEntry();}} catch (IOException e) {e.printStackTrace();if (bis!=null) {try {bis.close();} catch (IOException ee){}}if (zis!=null) {try {zis.close();} catch (IOException ee){}}}return list;}}}
压缩文件测试代码:
public class ZipUtilTest {@Testpublic void testZipFile() {try {// 读取文件1File file1 = new File("E:\\project\\java\\src\\main\\resources\\zip\\zip1.text");FileInputStream fis1 = new FileInputStream(file1);byte[] fileBytes1 = new byte[fis1.available()];fis1.read(fileBytes1);// 读取文件2File file2 = new File("E:\\project\\java\\src\\main\\resources\\zip\\zip2.text");FileInputStream fis2 = new FileInputStream(file1);byte[] fileBytes2 = new byte[fis2.available()];fis2.read(fileBytes2);// 获取压缩包文件字节数组byte[] bytes = ZipUtil.createZipObject().addFile(fileBytes1, file1.getName()).addFile(fileBytes2, file2.getName()).create();/*** 如果是响应给浏览器的话,可以:* HttpServletResponse.getOutputStream().write(bytes[]);*/// 将压缩包数据写到本地FileOutputStream fos = new FileOutputStream("E:\\project\\java\\src\\main\\resources\\zip\\hello.zip");fos.write(bytes);} catch (Exception e) {e.printStackTrace();}}}
解压文件测试代码:
@Test
public void testUnZipFile() {try {// 读取压缩文件File file = new File("E:\\project\\java\\src\\main\\resources\\zip\\hello.zip");FileInputStream fis1 = new FileInputStream(file);byte[] fileBytes1 = new byte[fis1.available()];fis1.read(fileBytes1);ZipUtil.UnZipObject unZipObject = ZipUtil.createUnZipObject(fileBytes1);List<ZipEntry> entryList = unZipObject.getEntrys();System.out.println("entryList:"+entryList.size());entryList.forEach(zipEntry -> {try {// zipEntry.getName() 压缩包里面的文件名FileOutputStream fos = new FileOutputStream("E:\\project\\"+zipEntry.getName());// zipEntry.getExtra()是压缩包里面的一个个文件数据fos.write(zipEntry.getExtra());fos.close();} catch (Exception e) {e.printStackTrace();}});} catch (Exception e) {e.printStackTrace();}
}