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;
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章