Java解压缩zip文件

java8zip


发表于 2017-10-11 19:52


jdk1.7:

static void unzip(File zip, File dir, Charset charset) throws IOException {
	// create output directory if it doesn't exist
	if (!dir.exists())
		dir.mkdirs();
	try (FileInputStream fis = new FileInputStream(zip);
			ZipInputStream zis = new ZipInputStream(fis, charset == null ? StandardCharsets.UTF_8 : charset)) {
		byte[] buffer = new byte[1024];
		ZipEntry ze = zis.getNextEntry();
		while (ze != null) {
			if (ze.isDirectory()) {
				ze = zis.getNextEntry();
				continue;
			}
			String fileName = ze.getName();
			File newFile = new File(dir, fileName);
			System.out.println("Unzipping to " + newFile.getAbsolutePath());
			// create directories for sub directories in zip
			new File(newFile.getParent()).mkdirs();
			try (FileOutputStream fos = new FileOutputStream(newFile)) {
				int len;
				while ((len = zis.read(buffer)) > 0) {
					fos.write(buffer, 0, len);
				}
				fos.close();
			}
			// close this ZipEntry
			zis.closeEntry();
			ze = zis.getNextEntry();
		}
		// close last ZipEntry
		zis.closeEntry();
		zis.close();
		fis.close();
	}
}

jdk1.8:

static void unzip(Path zip, Map<String, String> env, Path dir) throws IOException {

	URI uri;
	try {
		uri = new URI("jar", zip.toUri().toString(), null);
	} catch (URISyntaxException e) {
		throw new IOException(e.getMessage(), e);
	}

	try (FileSystem fs = FileSystems.newFileSystem(uri, env)) {
		Path root = fs.getPath("/");

		Files.walk(root).filter(FileUtils::isRegularFile).parallel().forEach(p -> {
			Path dest = dir.resolve(FileUtils.cleanPath(p.toString()));
			try {
				Files.createDirectories(dest.getParent());
				System.out.println("Unzipping to " + dest);
				Files.copy(p, dest);
			} catch (IOException e) {
				throw new RuntimeException(e.getMessage(), e);
			}
		});
	}
}

关于java.lang.IllegalArgumentException: MALFORMED错误,1.7以下只需要更改Charset即可,在1.8中需要通过设置env来解决这个问题,例如:

Map<String, String> env = new HashMap<>();
env.put("encoding", "gbk");
unzip(Paths.get("f:/1.zip"), env, Paths.get("f:/test"));

另外在1.8中,通过parallel()方法可以方便的使用并行流来减少解压缩时间。

如果是密码保护的zip文件,还是老老实实的用zip4j吧,官网地址: http://www.lingala.net/zip4j/

实际使用发现,java8的方法有时候会出现一些让人摸不着头脑的问题,例如 https://stackoverflow.com/questions/14654737/nosuchfileexception-while-walking-files-tree-inside-a-zip-using-java-nio 我在某些压缩包中碰到了这个问题,似乎也没有什么解决办法,所以还是采用了1.7之前的方法。,


搜索