java實現zip文件解壓縮教程

說明

最近開發有將文件打包成zip文件的需求,以供瀏覽器直接點擊下載。這裏可以使用JDK提供的相關方法,也可以使用第三方commons-compress提供的相關方法,這裏需要注意的是以下幾點:

  1. 需要滿足可以壓縮文件也可以是文件夾的需求。
  2. 壓縮的時候能滿足多級目錄的需求。
  3. 空文件夾如需保存需特殊指明,否則空文件夾並不會進行壓縮。
  4. 對於任何一個錯誤的文件路徑,其默認類型爲文件夾類型。

JDK方法解壓縮

在解壓縮文件中,使用到的JDK相關類如下所示:

import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

可以使用java.util.zip包中的Deflater類常量可以指定壓縮級別,這些常數是如下圖所示:

ZipEntry對象表示Zip文件格式的歸檔文件中的條目,ZipInputStreamZipOutputStream是讀取zip文件的輸入、輸出流。下面將演示如何解壓縮zip文件。

  • 壓縮文件
 /**
     * 壓縮文件
     * @param zos 輸出流1
     * @param file 壓縮的文件對象
     */
    public static void compressZipFile(ZipOutputStream zos, File file) {
        File[] files = file.listFiles();
        try {
            if (file.isFile()) {
                writeZipEntry(zos, file);
            } else {
                // 空文件夾
                if (files.length == 0) {
                    ZipEntry zipEntry = new ZipEntry(file.getPath() + File.separator);
                    zos.putNextEntry(zipEntry);
                    zos.closeEntry();
                }
                // 遞歸調用
                for (File f : files) {
                    compressZipFile(zos, f);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 寫zip entry對象
     * @param zos
     * @param f
     */
    private static void writeZipEntry(ZipOutputStream zos, File f) {
        BufferedInputStream bis = null;
        try {
            ZipEntry zipEntry = new ZipEntry(f.getPath());
            zos.putNextEntry(zipEntry);
            bis = new BufferedInputStream(new FileInputStream(f));
            int len;
            byte[] bytes = new byte[1024];
            while ((len = bis.read(bytes)) != -1) {
                zos.write(bytes, 0, len);
            }
            zos.closeEntry();
            bis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 
  • 解壓文件
 /**
     * 解壓文件夾
     * @param zis 輸入流
     * @param path 解壓到path路徑下
     */
    public static void deCompressZipFile(ZipInputStream zis, String path) {
        ZipEntry zipEntry = null;
        try {
            while ((zipEntry = zis.getNextEntry()) != null) {
                File file = new File(path + File.separator + zipEntry.getName());

                // 如果目錄不存在就創建
                File parentFile = file.getParentFile();
                if (!parentFile.exists()) {
                    parentFile.mkdirs();
                }
                if (!zipEntry.isDirectory()) {
                    // 讀取Entry對象

                    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
                    byte[] bytes = new byte[1024];
                    int len;
                    while ((len = zis.read(bytes)) != -1) {
                        bos.write(bytes, 0, len);
                    }
                    bos.close();
                } else {
                    file.mkdirs();
                }

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

測試執行

public static void main(String[] args) throws IOException {
        Scanner scanner = new Scanner(System.in);
        System.out.println("請輸入壓縮的文件目錄");
        String line = scanner.nextLine().trim();
        File file = new File(line);
        if (!file.exists()) {
            System.out.println("輸入的路徑不合法");
            return;
        }
        File zipFile = new File("test.zip");

        ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)));
        zos.setLevel(Deflater.BEST_COMPRESSION);
        // 壓縮文件
        compressZipFile(zos, file);
        zos.close();
        File f = new File("test.zip");
        ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(f)));
        // 解壓zip
        deCompressZipFile(zis, f.getAbsolutePath().replaceAll(File.separator + f.getName(), ""));
        zis.close();
    }

commons-compress解壓縮

首先引入相關pom依賴如下所示:

        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.3</version>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-compress</artifactId>
            <version>1.18</version>
        </dependency>

commons-compress是Apache開源組織提供的用於壓縮解壓的工具包,其可以支持以下文件格式的文件解壓縮,如下圖所示:

下面演示如何解壓縮。

  • 壓縮文件
 /**
     *
     * @param srcPath 原文件路徑
     * @param destFile 壓縮文件路徑
     */
    public static void zipFile(String srcPath, String destFile) {
        File outFile = new File(destFile);
        FileOutputStream fos = null;
        BufferedOutputStream bufferedOutputStream = null;
        ArchiveOutputStream out = null;
        try {
            if (!outFile.exists()) {
                outFile.createNewFile();
            }
            fos = new FileOutputStream(outFile);
            bufferedOutputStream = new BufferedOutputStream(fos);
            out = new ArchiveStreamFactory().createArchiveOutputStream(
                    ArchiveStreamFactory.ZIP, bufferedOutputStream);

            if (srcPath.charAt(srcPath.length() - 1) != '/') {
                srcPath += '/';
            }
            File f = new File(srcPath);
            // 如果是文件夾
            if(f.isDirectory()) {
                Iterator<File> files = FileUtils.iterateFiles(f,
                        null, true);
                System.out.println(f.getAbsolutePath());
                while (files.hasNext()) {
                    File file = files.next();
                    writeEntry(srcPath, out, file);
                }
            } else {
                writeEntry(srcPath, out, f);
            }

            out.finish();
            out.close();
            bufferedOutputStream.close();
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();

        } catch (ArchiveException e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (bufferedOutputStream != null) {
                    bufferedOutputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private static void writeEntry(String srcPath, ArchiveOutputStream out, File file) throws IOException {
        ZipArchiveEntry zipArchiveEntry = new ZipArchiveEntry(file,
                file.getPath().replace(srcPath.replace("/", "\\"), ""));

        out.putArchiveEntry(zipArchiveEntry);
        IOUtils.copy(new FileInputStream(file), out);
        out.closeArchiveEntry();
    }
  • 解壓文件
public static void deCompressZip(String zipPath) throws Exception
   {
      InputStream stream = new FileInputStream(zipPath);
      ZipArchiveInputStream inputStream = new ZipArchiveInputStream(stream);
      ZipArchiveEntry entry = null;
      while ((entry = inputStream.getNextZipEntry()) != null)
      {
         System.out.println(entry.getName());
         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
         //讀取內容
         IOUtils.copy(inputStream, outputStream);
         System.out.println(outputStream.toString());
      }
      inputStream.close();
      stream.close();
   }

發佈了65 篇原創文章 · 獲贊 19 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章