java壓縮與解壓縮

主要用到apache的ant.jar,也可用jdk的相關類,但會有中文亂碼問題。最重要的倆類是ZipFile和ZipEntry,前者將zip文件轉爲java對象,後者將zip文件中的條目文件轉爲java對象。 核心代碼以下:java

壓縮代碼:apache

ZipOutputStream zipOs = new ZipOutputStream(fos);
ZipEntry zipEntry = new ZipEntry("entryName");
zipOs.putNextEntry(zipEntry);

解壓縮代碼:測試

Enumeration<ZipEntry> entries = zipFile.getEntries();
ZipEntry zipEntry = entries.nextElement();
InputStream ins = zipFile.getInputStream(zipEntry);

須要注意的地方:code

針對空文件夾須要特殊處理,須要往Entry中放入"/"+文件夾名+"/"項對象

zipOs.putNextEntry("/");

詳細點的練習: /** * 測試文件壓縮與解壓縮 * */ public class TestZip {遞歸

public static void main(String[] args) {
		//-->壓縮單個文件
		zipSingleFileOrFolder("D:\\BIZFLOW\\src\\tst\\新建文本文檔.zip", "D:\\BIZFLOW\\src\\tst\\新建文本文檔.txt");
		//-->壓縮文件夾
		//zipSingleFileOrFolder("D:\\BIZFLOW\\src\\tst.zip", "D:\\BIZFLOW\\src\\tst");
		//-->壓縮多個文件(不指定壓縮文件保存路徑)
		//zipMultiFiles("","D:\\BIZFLOW\\src\\tst\\新建文本文檔.txt","D:\\BIZFLOW\\src\\tst\\新建文本文檔 - 副本.txt");
		//-->壓縮多個文件(指定壓縮文件保存路徑)
		//zipMultiFiles("D:\\BIZFLOW\\src\\tst\\新建.zip","D:\\BIZFLOW\\src\\tst\\新建文本文檔.txt","D:\\BIZFLOW\\src\\tst\\新建文本文檔 - 副本.txt");
		//-->解壓縮文件
		//unzipFile("D:\\BIZFLOW\\src\\tst\\新建", "D:\\BIZFLOW\\src\\tst\\新建文本文檔.txt等.zip");
	}
	
	/**
	 * 壓縮單個文件/文件夾
	 * @param destPath 壓縮文件保存路徑(爲空串/null時默認壓縮路徑:待壓縮文件所在目錄,壓縮文件名爲待壓縮文件/文件夾名+「等.zip」)
	 * @param srcPath 待壓縮的文件路徑
	 */
	public static void zipSingleFileOrFolder(String destPath, String srcPath) {
		if(StringUtils.isBlank(srcPath)) {
			throw new RuntimeException("待壓縮文件夾不可爲空!");
		}
		if(StringUtils.isNotBlank(destPath) && !destPath.endsWith(".zip")) {
			throw new RuntimeException("保存文件名應以.zip結尾!");
		}
		File file = new File(srcPath);
		if(!file.exists()) {
			throw new RuntimeException("路徑'"+srcPath+"'下未找到文件");
		}
		if(file.isDirectory()) {
			//壓縮文件夾
			zipFolder(destPath, srcPath);
		} else {
			//壓縮單個文件
			zipFile(destPath, srcPath); 
		}
	}
	
	/**
	 * 壓縮多個文件
	 * @param destPath 壓縮文件保存路徑(爲空串/null時默認壓縮路徑:待壓縮文件所在目錄,壓縮文件名爲第一個待壓縮文件名+「等.zip」)
	 * @param srcPaths 待壓縮文件路徑集合
	 */
	public static void zipMultiFiles(String destPath, String...srcPaths) {
		if(srcPaths==null || srcPaths.length==0) {
			throw new RuntimeException("待壓縮文件夾不可爲空!");
		}
		if(StringUtils.isNotBlank(destPath) && !destPath.endsWith(".zip")) {
			throw new RuntimeException("保存文件名應以.zip結尾!");
		}
		zipFiles(destPath, srcPaths);
	}
	
	/**
	 * 解壓縮文件
	 * @param destPath 解壓縮路徑(爲空串/null時默認解壓縮路徑:壓縮文件所在目錄)
	 * @param zipPath 壓縮文件路徑
	 */
	public static void unzipFile(String destPath, String zipPath) {
		if(StringUtils.isBlank(zipPath)) {
			throw new RuntimeException("壓縮文件路徑不可爲空!");
		}
		if(!zipPath.endsWith(".zip")) {
			throw new RuntimeException("保存文件名應以.zip結尾!");
		}
		File file = new File(zipPath);
		if(StringUtils.isBlank(destPath)) {
			destPath = getUnzipBasePath(file);
		}
		if(!file.exists()) {
			throw new RuntimeException("路徑'"+zipPath+"'下未找到文件");
		}
		ZipFile zipFile;
		int len;
		byte[] buff = new byte[1024];
		try {
			zipFile = new ZipFile(zipPath);
			//獲取壓縮文件中全部條目
			Enumeration<ZipEntry> entries = zipFile.getEntries();
			if(entries!=null) {
				while(entries.hasMoreElements()) {
					//壓縮文件條目轉爲文件或文件夾
					ZipEntry zipEntry = entries.nextElement();
					//獲取輸入流
					InputStream ins = zipFile.getInputStream(zipEntry);
					BufferedInputStream bis = new BufferedInputStream(ins);
					File unzipFile = new File(destPath+File.separator+zipEntry.getName());
					if(zipEntry.isDirectory()) {
						unzipFile.mkdirs();
						continue;
					} 
					
					File pf = unzipFile.getParentFile();
					if(pf!=null && !pf.exists()) {
						pf.mkdirs();
					}
					unzipFile.createNewFile();
					FileOutputStream fos = new FileOutputStream(unzipFile);
					BufferedOutputStream bos = new BufferedOutputStream(fos);
					//輸出流寫文件
					while((len=bis.read(buff, 0, 1024))!=-1) {
						bos.write(buff, 0, len);
					}
					bos.flush();
					fos.close();
					bos.close();
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
			throw new RuntimeException();
		}
		
	}
	
	/**
	 * 獲取解壓縮文件基路徑
	 * @param zipPath
	 * @return 
	 */
	private static String getUnzipBasePath(File zipPath) {
		return zipPath.getParentFile().getAbsolutePath();
	}
	
	/**
	 * 壓縮單個文件
	 * @param destPath 壓縮文件保存路徑
	 * @param srcPath 待壓縮文件路徑
	 */
	private static void zipFile(String destPath, String srcPath) {
		zipFiles(destPath, srcPath);
	}
	/**
	 * 壓縮多個文件
	 * @param srcPath
	 * @param zipPath
	 */
	private static void zipFiles(String destPath, String...srcPaths) {
		if(StringUtils.isBlank(destPath)) {
			File srcFile0 = new File(srcPaths[0]);
			destPath = srcFile0.getParentFile().getAbsolutePath()+File.separator+srcFile0.getName()+"等.zip";
		}
		File zipFile = new File(destPath);
		FileOutputStream fos = null;
		try {
			zipFile.createNewFile();
			zipFile.mkdirs();
			fos = new FileOutputStream(zipFile);
		} catch (IOException e) {
			e.printStackTrace();
			throw new RuntimeException();
		}
		//獲取輸出流
		ZipOutputStream zipOs = new ZipOutputStream(fos);
		//循環將多個文件轉爲壓縮文件條目
		for(String srcPath : srcPaths) {
			if(StringUtils.isBlank(srcPath)) {
				throw new RuntimeException("待壓縮文件路徑不可爲空!");
			}
			File srcFile = new File(srcPath);
			try {
				ZipEntry zipEntry = new ZipEntry(srcFile.getName());
				zipOs.putNextEntry(zipEntry);
				//獲取輸入流
				FileInputStream fis = new FileInputStream(srcFile);
				int len;
				byte[] buff = new byte[1024];
				//輸入/輸出流對拷
				while((len=fis.read(buff))!=-1) {
					zipOs.write(buff, 0, len);
				}
				fis.close();
			} catch (FileNotFoundException e) {
				e.printStackTrace();
				throw new RuntimeException();
			} catch (IOException e) {
				e.printStackTrace();
				throw new RuntimeException();
			}
		}
		try {
			zipOs.flush();
			zipOs.close();
		} catch (IOException e) {
			e.printStackTrace();
			throw new RuntimeException();
		}
	}
	
	/**
	 * 壓縮文件夾
	 * @param destPath 壓縮文件保存路徑
	 * @param srcPath 待壓縮文件夾路徑
	 */
	private static void zipFolder(String destPath, String srcPath) {
		File srcFile = new File(srcPath);
		//如壓縮文件保存路徑爲空,則默認保存路徑
		if(StringUtils.isBlank(destPath)) {
			destPath = srcFile.getParent()+File.separator+srcFile.getName()+".zip";
		}
		FileOutputStream fos = null;
		ZipOutputStream zipOs = null;
		try {
			fos = new FileOutputStream(destPath);
			zipOs = new ZipOutputStream(fos);
			//遞歸往壓縮文件中添加文件夾條目
			zipFolder(srcFile, srcFile, zipOs);
			zipOs.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			throw new RuntimeException();
		} catch (IOException e) {
			e.printStackTrace();
			throw new RuntimeException();
		}
	}
	
	/**
	 * 遞歸往壓縮文件中添加文件夾條目
	 * @param srcFile 待壓縮文件夾路徑
	 * @param baseFile 
	 * @param zipOs
	 */
	private static void zipFolder(File srcFile, File baseFile, ZipOutputStream zipOs) {
		int len;
		byte[] buff = new byte[1024];
		if(srcFile.isDirectory()) {
			//針對空文件夾須要特殊處理,須要往Entry中放入"/"+文件夾名+"/"項
			try {
				zipOs.putNextEntry(new ZipEntry(srcFile.getAbsolutePath().replaceFirst(baseFile.getParentFile().getAbsolutePath().replaceAll("\\\\", "\\\\\\\\"), "")+"/"));
				zipOs.closeEntry();
			} catch (IOException e) {
				e.printStackTrace();
				throw new RuntimeException();
			}
			//獲取當前文件夾下文件列表
			File[] fileLists = srcFile.listFiles();
			if(fileLists!=null && fileLists.length>0) {
				for (int i = 0; i < fileLists.length; i++) {
					//遞歸往壓縮文件中添加文件夾條目
					zipFolder(fileLists[i], baseFile, zipOs);
				}
			}
		} else {
			//文件處理比較簡單,直接放入Entry
			try {
				FileInputStream fis = new FileInputStream(srcFile);
				zipOs.putNextEntry(new ZipEntry(getRelativePath(baseFile.getAbsolutePath(), srcFile)));
				while((len=fis.read(buff))!=-1) {
					zipOs.write(buff, 0, len);
				}
				zipOs.closeEntry();
				fis.close();
			} catch (IOException e) {
				e.printStackTrace();
				throw new RuntimeException();
			}
		}
	}
	
	/**
	 * 獲取相對基路徑的相對路徑
	 * @param basePath
	 * @param file
	 * @return
	 */
	private static String getRelativePath(String basePath, File file) {
		if(!basePath.equalsIgnoreCase(file.getAbsolutePath())) {
			return getRelativePath(basePath, file.getParentFile())+File.separator+file.getName();
		} else {
			return file.getName();
		}
	}
	
}
相關文章
相關標籤/搜索