通過jdk1.7nio實現對zip包的壓縮和解壓

將目標目錄打包壓縮到zip包中,通過jdk1.7的Files.walkFileTree原理實現,參考代碼如下:

/**
     * 將目標文件或者文件夾壓縮到zip中
     * 
     * @param zipOutpusStream zip輸出流
     * @param target 需要壓縮的目標目錄
     * @param ignoreEntryNames 忽略壓縮目錄
     * @throws IOException IOException
     */
    public static void zip(OutputStream zipOutpusStream, Path target, List<Path> ignoreEntryNames) throws IOException {
        ZipOutputStream out = new ZipOutputStream(zipOutpusStream);
        Files.walkFileTree(target, EnumSet.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE,
            new ZipDirectoryVisitor(out, target, ignoreEntryNames));
        if (out != null) {
            out.close();
        }
    }
package xxx.nio;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * ZIP包輸出訪問器
 * 
 * @author 許暢
 * @since JDK1.7
 * @version 2019年4月8日 許暢 新建
 */
public class ZipDirectoryVisitor extends SimpleFileVisitor<Path> {
    
    /** zip輸出流 */
    private ZipOutputStream out;
    
    /** zip包中存儲相對路徑 */
    private Path relativePath;
    
    /** zip包中需要忽略的entry名稱 */
    private List<Path> ignoreEntryNames;
    
    /**
     * 構造方法
     * 
     * @param out ZIP輸出流
     * @param relativePath ZIP包存儲相對路徑
     */
    public ZipDirectoryVisitor(ZipOutputStream out, Path relativePath) {
        setOut(out);
        setRelativePath(relativePath);
    }
    
    /**
     * 構造方法
     * 
     * @param out ZIP輸出流
     * @param relativePath ZIP包存儲相對路徑
     * @param ignoreEntryNames zip包中需要忽略的entry名稱
     */
    public ZipDirectoryVisitor(ZipOutputStream out, Path relativePath, List<Path> ignoreEntryNames) {
        setOut(out);
        setRelativePath(relativePath);
        setIgnoreEntryNames(ignoreEntryNames);
    }
    
    /**
     * 訪問文件
     * 
     * @param file 文件路徑
     * @param attributes 屬性
     * @return FileVisitResult
     * @throws IOException IO異常
     */
    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) throws IOException {
        Path entryName = relativePath.relativize(file);
        if (ignoreEntryNames == null || !ignoreEntryNames.contains(entryName)) {
            addEntry(file.toFile(), entryName);
        }
        return FileVisitResult.CONTINUE;
    }
    
    @Override
    public FileVisitResult preVisitDirectory(Path directory, BasicFileAttributes attributes) throws IOException {
        return FileVisitResult.CONTINUE;
    }
    
    /**
     * 添加ZIP包的entry
     * 
     * @param inFile ZIP輸入文件
     * @param entryName ZIP的文件名
     * @throws IOException IOException
     */
    private void addEntry(File inFile, Path entryName) throws IOException {
        ZipEntry entry = new ZipEntry(entryName.toString());
        out.putNextEntry(entry);
        
        int len = 0;
        byte[] buffer = new byte[1024];
        FileInputStream fis = new FileInputStream(inFile);
        while ((len = fis.read(buffer)) > 0) {
            out.write(buffer, 0, len);
            out.flush();
        }
        out.closeEntry();
        fis.close();
    }
    
    /**
     * @return 獲取 out屬性值
     */
    public ZipOutputStream getOut() {
        return out;
    }
    
    /**
     * @param out 設置 out 屬性值爲參數值 out
     */
    public void setOut(ZipOutputStream out) {
        this.out = out;
    }
    
    /**
     * @return 獲取 relativePath屬性值
     */
    public Path getRelativePath() {
        return relativePath;
    }
    
    /**
     * @param relativePath 設置 relativePath 屬性值爲參數值 relativePath
     */
    public void setRelativePath(Path relativePath) {
        this.relativePath = relativePath;
    }
    
    /**
     * @return 獲取 ignoreEntryNames屬性值
     */
    public List<Path> getIgnoreEntryNames() {
        return ignoreEntryNames;
    }
    
    /**
     * @param ignoreEntryNames 設置 ignoreEntryNames 屬性值爲參數值 ignoreEntryNames
     */
    public void setIgnoreEntryNames(List<Path> ignoreEntryNames) {
        this.ignoreEntryNames = ignoreEntryNames;
    }
    
}

將zip包解壓到指定文件夾,直接通過jdk io實現,參考代碼如下:

/**
     * 將zip包解壓到目標目錄
     * 
     * @param zipInputstream zip輸入流
     * @param destDir 需要解壓的目標目錄
     * @param ignorePatterns 忽略解壓目錄
     * @throws IOException IOException
     */
    public static void unzip(InputStream zipInputstream, Path destDir, List<String> ignorePatterns) throws IOException {
        if (!Files.exists(destDir)) {
            Files.createDirectories(destDir);
        }
        byte[] buffer = new byte[1024];
        ZipInputStream zis = new ZipInputStream(zipInputstream);
        ZipEntry zipEntry = zis.getNextEntry();
        AntPathMatcher antPathMatcher = new AntPathMatcher();
        while (zipEntry != null) {
            if (isIgnoreMatch(ignorePatterns, zipEntry.getName(), antPathMatcher)) {
                zipEntry = zis.getNextEntry();
                continue;
            }
            Path destFile = destDir.resolve(zipEntry.getName());
            if (zipEntry.isDirectory()) {
                if (!Files.exists(destFile)) {
                    Files.createDirectories(destFile);
                }
            } else {
                if (!Files.exists(destFile) && !Files.exists(destFile.getParent())) {
                    // 創建上級文件夾
                    Files.createDirectories(destFile.getParent());
                }
                FileOutputStream fos = new FileOutputStream(destFile.toFile());
                int len;
                while ((len = zis.read(buffer)) > 0) {
                    fos.write(buffer, 0, len);
                }
                fos.close();
                zipEntry = zis.getNextEntry();
            }
        }
        zis.closeEntry();
        zis.close();
    }
 /**
     * @param ignorePatterns 忽略正則
     * @param entryName 目錄名稱
     * @param antPathMatcher AntPathMatcher
     * @return 是否忽略
     */
    private static boolean isIgnoreMatch(List<String> ignorePatterns, String entryName, AntPathMatcher antPathMatcher) {
        if (ignorePatterns != null) {
            for (String ignorePattern : ignorePatterns) {
                if (antPathMatcher.match(ignorePattern, entryName)) {
                    return true;
                }
            }
        }
        return false;
    }

 

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