作者:zyl910
有些时候需要替换zip内的文件。
网上的办法大多是——先解压,然后对解压目录替换文件,最后再重新压缩。该办法需要比较繁琐,且需要一个临时目录。
于是想找无需解压的方案。
后来找到利用 ZipInputStream、ZipOutputStream 实现该功能的办法。
import java.io.*; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; public class ZipCopyTest { public static void main(String[] args) { String srcPath = "target/classes/static/test.docx"; String outPath = "E://test//export//test_copy.docx"; try(FileInputStream is = new FileInputStream(srcPath)) { try(FileOutputStream os = new FileOutputStream(outPath)) { copyZipStream(os, is); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } System.out.println("ZipCopyTest done."); } private static void copyZipStream(OutputStream os, InputStream is) throws IOException { try(ZipInputStream zis = new ZipInputStream(is)) { try(ZipOutputStream zos = new ZipOutputStream(os)) { ZipEntry se; while ((se = zis.getNextEntry()) != null) { if (null==se) continue; String line = String.format("ZipEntry(%s, isDirectory=%d, size=%d, compressedSize=%d, time=%d, crc=%d, method=%d, comment=%s)", se.getName(), (se.isDirectory())?1:0, se.getSize(), se.getCompressedSize(), se.getTime(), se.getCrc(), se.getMethod(), se.getComment()); System.out.println(line); ZipEntry de = new ZipEntry(se); zos.putNextEntry(de); copyStream(zos, zis); zos.closeEntry(); } } } } private static void copyStream(OutputStream os, InputStream is) throws IOException { copyStream(os, is, 0); } private static void copyStream(OutputStream os, InputStream is, int bufsize) throws IOException { if (bufsize<=0) bufsize= 4096; int len; byte[] bytes = new byte[bufsize]; while ((len = is.read(bytes)) != -1) { os.write(bytes, 0, len); } } }
现在已经实现zip内项目的逐项复制了。只要稍微改造一下,便能实现“替换zip内的文件”的功能了。
具体办法是在循环内根据 ZipEntry.getName()
判断当前是哪一个文件,随后不是简单的调用 copyStream,而是改为根据自己需要对流数据进行处理。