基於JDK API實現文件的壓縮與解壓

在實際開發過程中,會經常遇到下載附件或者導出報表的情況,有時候文件會比較多,用戶更希望多個文件可以一起打包進行下載。這時就需要實現兩部分功能:一部分是多個文件的打包處理,一部分是壓縮文件的下載功能。

對於壓縮文件的下載,可查看我的另一篇博文(SpringMVC下打包文件的下載),本文主要提供多個文件的壓縮與解壓的例子。樣例完全基於JDK自帶的IO流處理類,主要相關類爲ZipInputStream和ZipOutputStream,使用JDK API已經能夠滿足壓縮與解壓的需求。我看網上有不少提到壓縮中文亂碼的問題,建議用ant.jar中包的ZIP處理類進行處理,我進行了相關測試:使用JDK1.6進行壓縮會出現壓縮包中的文件中文名亂碼,但是使用JDK1.7或者JDK1.8不會亂碼。

所以本樣例正常運行需要使用JDK1.7+的版本。

另注:本樣例仍然有個問題有待解決:我分別使用txt文件、excel文件、word文件進行壓縮測試,壓縮正常,使用WinRAR工具解壓後文件也能正常查看。但是使用JDK的IO流解壓後,只有txt文件查看正常,excel與word文件都損壞了,無法正常查看。這個問題仍未找到原因與解決方案,若有大神告知,感激不盡。

下面直接上代碼:
一、壓縮與解壓工具類

ZipUtils.java 

package research.j2se.io;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

/**
 * 使用JDK自帶的Zip處理類進行文件的壓縮與解壓
 *
 */
public class ZipUtils {
	
	/**
	 * 壓縮文件(一個或多個)到指定壓縮包
	 */
	public static void zip( String targetFilePath, String ... sourceFilePaths){
		if( sourceFilePaths == null || sourceFilePaths.length == 0 ){
			return;
		}
		try {
			File targetFile = new File(targetFilePath);
			ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(targetFile));
			BufferedInputStream bis = null;
			byte [] buffer = new byte[512];
			for( int i = 0; i < sourceFilePaths.length; i++ ){
				File sourceFile = new File(sourceFilePaths[i]);
				if( sourceFile.exists() ){
					//目標文件不存在則創建文件
					if( ! targetFile.exists() ){
						targetFile.createNewFile();
					}
					String sourceFileName = sourceFile.getName();
					ZipEntry entry = new ZipEntry(sourceFileName);
					//設置壓縮包的入口
					zos.putNextEntry(entry);
					bis = new BufferedInputStream(new FileInputStream(sourceFile));
					while( bis.read(buffer) != -1){
						zos.write(buffer);
					}
				}
			}
			bis.close();
			zos.flush();
			zos.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 解壓文件到指定目錄
	 */
	public static void unzip(String targetDirPath, String ... sourceFilePaths){
		if( sourceFilePaths == null || sourceFilePaths.length == 0 ){
			return;
		}
		//解壓目錄不存在則創建
		File targetDir = new File(targetDirPath);
		if( ! targetDir.exists() ){
			targetDir.mkdirs();
		}
		try {
			byte [] buffer = new byte[512];
			for( int i = 0; i < sourceFilePaths.length; i++ ){
				File sourceFile = new File(sourceFilePaths[i]);
				ZipInputStream zis = new ZipInputStream(new FileInputStream(sourceFile));
				ZipEntry entry = null;
				//遍歷壓縮文件的各個入口
				while( (entry=zis.getNextEntry()) != null ){
					String fileName = entry.getName();
					//創建對應的文件
					File file = new File(targetDirPath+File.separator + fileName);
					if( ! file.exists() ){
						file.createNewFile();
					}
					//進行文件的寫入
					BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file,true));
					while( zis.read(buffer) != -1 ){
						bos.write(buffer);
					}
					zis.closeEntry();
					bos.flush();
					bos.close();
				}
				zis.close();
			}
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch( Exception e ){
			e.printStackTrace();
		}
	}
	
}

 二、壓縮與解壓測試類

JdkZipUtilsTest.java

package research.j2se.io;

import junit.framework.TestCase;
import research.j2se.io.ZipUtils;

/**
 * jdk壓縮解壓工具類測試
 */
public class JdkZipUtilsTest
    extends TestCase
{
   
	/**
	 * 測試壓縮文件
	 */
    public void testZip()
    {
    	String targetFilePath = "src/main/resources/ziptarget/zip/壓縮.zip";
    	String sourceFilePath1 = "src/main/resources/zipsource/unzip/測試1.xlsx";
    	String sourceFilePath2 = "src/main/resources/zipsource/unzip/測試2.txt";
    	String sourceFilePath3 = "src/main/resources/zipsource/unzip/測試3.docx";
        ZipUtils.zip(targetFilePath, sourceFilePath1,sourceFilePath2,sourceFilePath3);
    }
    
    /**
     * 測試解壓文件(這裏Excel文件解壓無法打開,使用解壓工具可以打開)
     */
    public void testUnzip(){
    	String targetDirPath = "src/main/resources/ziptarget/unzip";
    	String sourceFilePath1 = "src/main/resources/zipsource/zip/壓縮.zip";
    	ZipUtils.unzip(targetDirPath, sourceFilePath1);
    }
}

 

本樣例測試通過。若要查看完整源碼,可訪問:https://github.com/wdmcygah/research-J2SE.git

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