Java中的Zip文件操作

0. 简介
  1. 简单的生成和读取 zip 文件
package com.willhonor.test;

import static java.nio.charset.StandardCharsets.UTF_8;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

import org.junit.Test;

/**
 * 有两处可能需要指定编码
 * <br>1. zipEntry 的名称和 comment 的编码可以单独指定
 * <br>2. zipEntry 的内容编码,该部分只需编码与解码方案一致即可,可以使用任意编码,
 * <br>即 如果写入数据时,使用 utf-8 编码,则读取数据时也使用 utf-8 解码即可。
 * @author jokee
 *
 */
public class Test_1 {
	/** 1. 生成 zip 文件 
	 * <br> a. 先指定 zipEntry 的名称,然后为其写入数据,这里的数据部分以字节数组的形式提供,
	 * <br>所以可以采用任意编码,当然在提取该 zipEntry 的数据内容时,也必须采用一致的解码方案。
	 */
	@Test
	public void test_generateZipFile() throws Exception {
		String zipFile = "E:\\temp\\temp\\docs.zip";
		// create new zip file
		File file = new File(zipFile);
		if (file.exists()) {
			file.delete();
		}
		file.createNewFile();
		// zipEntry 名称和 comment 使用 utf-8 编码
		ZipOutputStream zipOutputStream 
			= new ZipOutputStream(new FileOutputStream(file), UTF_8);
//		zipOutputStream.setComment("这是文档文件,压缩包");
		zipOutputStream.setComment("this is zip file, just for test.");
		// 1 first file,zipEntry 内容数据使用 utf-8 编码
		byte[] f1 = "hello this world, I'm here now, so happy!".getBytes(UTF_8);
		addEntry(zipOutputStream, "hello.txt", f1);
		// 2 second file
		byte[] f2 = "<p>这是我最喜欢的 blog 网站了</p>".getBytes(UTF_8);
		addEntry(zipOutputStream, "我的书签收藏.html", f2);
		// 4 empty directory
		addEntry(zipOutputStream, "others\\", null);		
		addEntry(zipOutputStream, "其它\\", null);		
		addEntry(zipOutputStream, "com\\", null);		
		addEntry(zipOutputStream, "com\\will\\", null);		
		addEntry(zipOutputStream, "com\\will\\honor\\", null);		
		// 3 third file
		byte[] f3 = "/** this is java source */".getBytes(UTF_8);
		addEntry(zipOutputStream, "com/will/honor/test.java", f3);
		// close
		zipOutputStream.close();
	}
	
	private void addEntry(ZipOutputStream os, String entityName, byte[] bytes) {
		try {
			ZipEntry entry = new ZipEntry(entityName);
			os.putNextEntry(entry);
			if (bytes != null && bytes.length > 0) {
				os.write(bytes);
			}
			os.closeEntry();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/** 读取/打印压缩文件内容,这里使用文本文件作为实验。通常 zip 文件中会包含例如 pdf/png 等格式的文件,不适合打印 */
	@Test
	public void test_useZipFileClass() throws Exception {
		String fileName = "E:\\temp\\temp\\docs.zip";
		// String fileName = "E:\\temp\\temp\\usediffcharset.zip";
		// zipEntry 名称和 commend 使用 utf-8 解码
		ZipFile zipFile = new ZipFile(new File(fileName), UTF_8);
		Enumeration<? extends ZipEntry> entries = zipFile.entries();
		while(entries.hasMoreElements()) {
			ZipEntry en = entries.nextElement();
			System.out.println(String.format("[%s]", new Object[] {en.getName()}));
			if (!en.isDirectory()) {
				InputStream is = zipFile.getInputStream(en);
				byte[] bytes = getAllBytes(is);
				// zipEntry 内容使用 utf-8 解码
				System.out.println(new String(bytes, UTF_8) + "\n---------------");
			}
		}
		zipFile.close();
	}
	
	public byte[] getAllBytes(InputStream is) {
		if (is != null) {
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			int bufSize = 1024;
			byte[] buf = new byte[bufSize];
			int res = 0;
			try {
				while((res = is.read(buf)) > 0) {
					out.write(buf, 0, res);
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			return out.toByteArray();
		}
		return null;
	}
	
	/**
	 * zipEntry 的名称使用 UTF-8 编码,而其数据内容使用 gbk 编码
	 */
	@Test
	public void test_useDifferentCharset() throws Exception {
		String fileName = "E:\\temp\\temp\\usediffcharset.zip";
		File file = new File(fileName);
		if (file.exists()) {
			file.delete();
		}
		file.createNewFile();
		ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(file), UTF_8);
		// add 1
		// zipEntry 名称使用 utf-8 编码
		zipOutputStream.putNextEntry(new ZipEntry("Java编程实战.txt"));
		// zipEntry 内容使用 gbk 编码
		zipOutputStream.write("这是Java编程实战,这是注释".getBytes(Charset.forName("gbk")));
		//
		zipOutputStream.close();
	}
}
  1. 压缩指定的目录或文件(zipEntry 名称和 comment 使用 utf-8 编码,zipEntry 内容保持不变,即不对 zipEntry 内容重新解码和编码)
package com.willhonor.test;

import static java.nio.charset.StandardCharsets.UTF_8;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.junit.Test;

/**
 * 压缩指定的目录 或 文件
 * @author jokee
 *
 */
public class Test_2 {
	public static final String FILE_SYSTEM_SEPARATOR = FileSystems.getDefault().getSeparator();
	
	public static void main(String[] args) {
		String path = "E:\\360Downloads\\Software";
		String zipFileName = "E:\\360Downloads\\";
		doZip(path, zipFileName);
	}
	
	/**
	 * 
	 * @param filePath 需要被压缩的目录或文件
	 * @param zipFileName 生成的压缩文件,如果为 null ,则生成的压缩文件处于 filePath 路径同级
	 */
	public static void doZip(String filePath, String zipFileName) {
		if (filePath != null) {
			Path path = Paths.get(filePath, new String[] {});
			if (Files.notExists(path, new LinkOption[] {LinkOption.NOFOLLOW_LINKS})) {
				System.out.println("指定路径不存在,path:" + path.toString());
				System.out.println("程序退出");
				System.exit(1);
			}
			Path parentPath = path.getParent();
			final int parentPathLen = parentPath.toString().length();
			zipFileName = getZipFileName(path, zipFileName);
			File zipFile = createZipFileIfNotExist(zipFileName);
			try {
				final ZipOutputStream os = new ZipOutputStream(new FileOutputStream(zipFile), UTF_8);
				if (Files.isDirectory(path, new LinkOption[] {LinkOption.NOFOLLOW_LINKS})) {
					// is directory
					Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
						@Override
						public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
								throws IOException {
							os.putNextEntry(new ZipEntry(dir.toString()
									.substring(parentPathLen + FILE_SYSTEM_SEPARATOR.length()) 
									+ FILE_SYSTEM_SEPARATOR));
							os.closeEntry();
							return FileVisitResult.CONTINUE;
						}
						@Override
						public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException {							
							os.putNextEntry(new ZipEntry(path.toString()
									.substring(parentPathLen + FILE_SYSTEM_SEPARATOR.length())));
							os.write(Files.readAllBytes(path));
							os.closeEntry();
							return FileVisitResult.CONTINUE;
						}
						@Override
						public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
							return FileVisitResult.CONTINUE;
						}
					});
				}else {
					// is a file
					os.putNextEntry(new ZipEntry(path.toString()
							.substring(parentPathLen + FILE_SYSTEM_SEPARATOR.length())));
					os.write(Files.readAllBytes(path));
					os.closeEntry();
				}
				os.close();
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	private static String getZipFileName(Path path, String zipFileName) {
		String fileName = path.getFileName().toString();
		if (zipFileName == null) {
			Path parenPath = path.getParent();
			zipFileName = parenPath.toString() + FILE_SYSTEM_SEPARATOR + fileName + ".zip";
		} else {			
			if (zipFileName.endsWith(FILE_SYSTEM_SEPARATOR)) {
				// zipFileName 为目录
				zipFileName += fileName;
			}
			if (!zipFileName.endsWith(".zip")) {
				zipFileName += ".zip";
			}
		}
		return zipFileName;
	}
	
	private static File createZipFileIfNotExist(String zipFileName) {
		File file = new File(zipFileName);
		if (!file.exists()) {
			File parentFile = file.getParentFile();
			if (parentFile != null && !parentFile.exists()) {
				parentFile.mkdirs();
			}
			try {
				file.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return file;
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值