最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java 如何實現(xiàn)解壓縮文件和文件夾

 更新時間:2021年03月11日 08:31:15   作者:Mr_ηobody  
這篇文章主要介紹了Java 如何實現(xiàn)解壓縮文件和文件夾,幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下

一 前言

項目開發(fā)中,總會遇到解壓縮文件的時候。比如,用戶下載多個文件時,服務端可以將多個文件壓縮成一個文件(例如xx.zip或xx.rar)。用戶上傳資料時,允許上傳壓縮文件,服務端進行解壓讀取每一個文件。

基于通用性,以下介紹幾種解壓縮文件的方式,包裝成工具類,供平時開發(fā)使用。

二 壓縮文件

壓縮文件,顧名思義,即把一個或多個文件壓縮成一個文件。壓縮也有2種形式,一種是將所有文件壓縮到同一目錄下,此種方式要注意文件重名覆蓋的問題。另一種是按原有文件樹結構進行壓縮,即壓縮后的文件樹結構保持不變。

壓縮文件操作,會使用到一個類,即ZipOutputStream。

2.1 壓縮多個文件

此方法將所有文件壓縮到同一個目錄下。方法傳入多個文件列表,和一個最終壓縮到的文件路徑名。

  /**
   * 壓縮多個文件,壓縮后的所有文件在同一目錄下
   * 
   * @param zipFileName 壓縮后的文件名
   * @param files 需要壓縮的文件列表
   * @throws IOException IO異常
   */
  public static void zipMultipleFiles(String zipFileName, File... files) throws IOException {
    ZipOutputStream zipOutputStream = null;
    try {
      // 輸出流
      zipOutputStream = new ZipOutputStream(new FileOutputStream(zipFileName));
      // 遍歷每一個文件,進行輸出
      for (File file : files) {
        zipOutputStream.putNextEntry(new ZipEntry(file.getName()));
        FileInputStream fileInputStream = new FileInputStream(file);
        int readLen;
        byte[] buffer = new byte[1024];
        while ((readLen = fileInputStream.read(buffer)) != -1) {
          zipOutputStream.write(buffer, 0, readLen);
        }
        // 關閉流
        fileInputStream.close();
        zipOutputStream.closeEntry();
      }
    } finally {
      if (null != zipOutputStream) {
        try {
          zipOutputStream.close();
        } catch (IOException ex) {
          ex.printStackTrace();
        }
      }
    }
  }

測試,將D盤下的infp.txt和infp1.txt文件壓縮到D盤下,壓縮文件名為my.zip。

  public static void main(String[] args) throws Exception {
    zipMultipleFiles("D:/my.zip", new File("D:/infp.txt"), new File("D:/infp1.txt"));
  }

2.2 壓縮文件或文件樹

此方法將文件夾下的所有文件按原有的樹形結構壓縮到文件中,也支持壓縮單個文件。原理也簡單,無非就是遞歸遍歷文件樹中的每一個文件,進行壓縮。有個注意的點每一個文件的寫入路徑是基于壓縮文件位置的相對路徑。

package com.nobody.zip;

import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

public class ZipUtils {

  /**
   * 壓縮文件或文件夾(包括所有子目錄文件)
   *
   * @param sourceFile 源文件
   * @param format 格式(zip或rar)
   * @throws IOException 異常信息
   */
  public static void zipFileTree(File sourceFile, String format) throws IOException {
    ZipOutputStream zipOutputStream = null;
    try {
      String zipFileName;
      if (sourceFile.isDirectory()) { // 目錄
        zipFileName = sourceFile.getParent() + File.separator + sourceFile.getName() + "."
            + format;
      } else { // 單個文件
        zipFileName = sourceFile.getParent()
            + sourceFile.getName().substring(0, sourceFile.getName().lastIndexOf("."))
            + "." + format;
      }
      // 壓縮輸出流
      zipOutputStream = new ZipOutputStream(new FileOutputStream(zipFileName));
      zip(sourceFile, zipOutputStream, "");
    } finally {
      if (null != zipOutputStream) {
        // 關閉流
        try {
          zipOutputStream.close();
        } catch (IOException ex) {
          ex.printStackTrace();
        }
      }
    }
  }

  /**
   * 遞歸壓縮文件
   * 
   * @param file 當前文件
   * @param zipOutputStream 壓縮輸出流
   * @param relativePath 相對路徑
   * @throws IOException IO異常
   */
  private static void zip(File file, ZipOutputStream zipOutputStream, String relativePath)
      throws IOException {

    FileInputStream fileInputStream = null;
    try {
      if (file.isDirectory()) { // 當前為文件夾
        // 當前文件夾下的所有文件
        File[] list = file.listFiles();
        if (null != list) {
          // 計算當前的相對路徑
          relativePath += (relativePath.length() == 0 ? "" : "/") + file.getName();
          // 遞歸壓縮每個文件
          for (File f : list) {
            zip(f, zipOutputStream, relativePath);
          }
        }
      } else { // 壓縮文件
        // 計算文件的相對路徑
        relativePath += (relativePath.length() == 0 ? "" : "/") + file.getName();
        // 寫入單個文件
        zipOutputStream.putNextEntry(new ZipEntry(relativePath));
        fileInputStream = new FileInputStream(file);
        int readLen;
        byte[] buffer = new byte[1024];
        while ((readLen = fileInputStream.read(buffer)) != -1) {
          zipOutputStream.write(buffer, 0, readLen);
        }
        zipOutputStream.closeEntry();
      }
    } finally {
      // 關閉流
      if (fileInputStream != null) {
        try {
          fileInputStream.close();
        } catch (IOException ex) {
          ex.printStackTrace();
        }
      }
    }
  }

  public static void main(String[] args) throws Exception {
    String path = "D:/test";
    String format = "zip";
    zipFileTree(new File(path), format);
  }
}

上例將test目錄下的所有文件壓縮到同一目錄下的test.zip文件中。

2.3 借助文件訪問器壓縮

還有一種更簡單的方式,我們不自己寫遞歸遍歷。借助Java原生類,SimpleFileVisitor,它提供了幾個訪問文件的方法,其中有個方法visitFile,對于文件樹中的每一個文件(文件夾除外),都會調用這個方法。我們只要寫一個類繼承SimpleFileVisitor,然后重寫visitFile方法,實現(xiàn)將每一個文件寫入到壓縮文件中即可。

當然,除了visitFile方法,它里面還有preVisitDirectory,postVisitDirectory,visitFileFailed等方法,通過方法名大家也猜出什么意思了。

package com.nobody.zip;

import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @Description
 * @Author Mr.nobody
 * @Date 2021/3/8
 * @Version 1.0.0
 */
public class ZipFileTree extends SimpleFileVisitor<Path> {

  // zip輸出流
  private ZipOutputStream zipOutputStream;
  // 源目錄
  private Path sourcePath;

  public ZipFileTree() {}

  /**
   * 壓縮目錄以及所有子目錄文件
   *
   * @param sourceDir 源目錄
   */
  public void zipFile(String sourceDir) throws IOException {
    try {
      // 壓縮后的文件和源目錄在同一目錄下
      String zipFileName = sourceDir + ".zip";
      this.zipOutputStream = new ZipOutputStream(new FileOutputStream(zipFileName));
      this.sourcePath = Paths.get(sourceDir);

      // 開始遍歷文件樹
      Files.walkFileTree(sourcePath, this);
    } finally {
      // 關閉流
      if (null != zipOutputStream) {
        zipOutputStream.close();
      }
    }
  }

  // 遍歷到的每一個文件都會執(zhí)行此方法
  @Override
  public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) throws IOException {
    // 取相對路徑
    Path targetFile = sourcePath.relativize(file);
    // 寫入單個文件
    zipOutputStream.putNextEntry(new ZipEntry(targetFile.toString()));
    byte[] bytes = Files.readAllBytes(file);
    zipOutputStream.write(bytes, 0, bytes.length);
    zipOutputStream.closeEntry();
    // 繼續(xù)遍歷
    return FileVisitResult.CONTINUE;
  }

  // 遍歷每一個目錄時都會調用的方法
  @Override
  public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
      throws IOException {
    return super.preVisitDirectory(dir, attrs);
  }

  // 遍歷完一個目錄下的所有文件后,再調用這個目錄的方法
  @Override
  public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
    return super.postVisitDirectory(dir, exc);
  }

  // 遍歷文件失敗后調用的方法
  @Override
  public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
    return super.visitFileFailed(file, exc);
  }

  public static void main(String[] args) throws IOException {
    // 需要壓縮源目錄
    String sourceDir = "D:/test";
    // 壓縮
    new ZipFileTree().zipFile(sourceDir);
  }
}

三 解壓文件

解壓壓縮包,借助ZipInputStream類,可以讀取到壓縮包中的每一個文件,然后根據(jù)讀取到的文件屬性,寫入到相應路徑下即可。對于解壓壓縮包中是文件樹的結構,每讀取到一個文件后,如果是多層路徑下的文件,需要先創(chuàng)建父目錄,再寫入文件流。

package com.nobody.zip;

import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

/**
 * @Description 解壓縮文件工具類
 * @Author Mr.nobody
 * @Date 2021/3/8
 * @Version 1.0.0
 */
public class ZipUtils {

  /**
   * 解壓
   * 
   * @param zipFilePath 帶解壓文件
   * @param desDirectory 解壓到的目錄
   * @throws Exception
   */
  public static void unzip(String zipFilePath, String desDirectory) throws Exception {

    File desDir = new File(desDirectory);
    if (!desDir.exists()) {
      boolean mkdirSuccess = desDir.mkdir();
      if (!mkdirSuccess) {
        throw new Exception("創(chuàng)建解壓目標文件夾失敗");
      }
    }
    // 讀入流
    ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(zipFilePath));
    // 遍歷每一個文件
    ZipEntry zipEntry = zipInputStream.getNextEntry();
    while (zipEntry != null) {
      if (zipEntry.isDirectory()) { // 文件夾
        String unzipFilePath = desDirectory + File.separator + zipEntry.getName();
        // 直接創(chuàng)建
        mkdir(new File(unzipFilePath));
      } else { // 文件
        String unzipFilePath = desDirectory + File.separator + zipEntry.getName();
        File file = new File(unzipFilePath);
        // 創(chuàng)建父目錄
        mkdir(file.getParentFile());
        // 寫出文件流
        BufferedOutputStream bufferedOutputStream =
            new BufferedOutputStream(new FileOutputStream(unzipFilePath));
        byte[] bytes = new byte[1024];
        int readLen;
        while ((readLen = zipInputStream.read(bytes)) != -1) {
          bufferedOutputStream.write(bytes, 0, readLen);
        }
        bufferedOutputStream.close();
      }
      zipInputStream.closeEntry();
      zipEntry = zipInputStream.getNextEntry();
    }
    zipInputStream.close();
  }

  // 如果父目錄不存在則創(chuàng)建
  private static void mkdir(File file) {
    if (null == file || file.exists()) {
      return;
    }
    mkdir(file.getParentFile());
    file.mkdir();
  }

  public static void main(String[] args) throws Exception {
    String zipFilePath = "D:/test.zip";
    String desDirectory = "D:/a";
    unzip(zipFilePath, desDirectory);
  }
}

四 總結

在解壓縮文件過程中,主要是對流的讀取操作,注意進行異常處理,以及關閉流。
web應用中,通過接口可以實現(xiàn)文件上傳下載,對應的我們只要把壓縮后的文件,寫入到response.getOutputStream()輸出流即可。
解壓縮文件時,注意空文件夾的處理。

此演示項目已上傳到Github,如有需要可自行下載,歡迎 Star 。 https://github.com/LucioChn/common-utils

以上就是Java 如何實現(xiàn)解壓縮文件和文件夾的詳細內容,更多關于Java 解壓縮文件和文件夾的資料請關注腳本之家其它相關文章!

相關文章

  • Nett中的心跳機制與斷線重連詳解

    Nett中的心跳機制與斷線重連詳解

    這篇文章主要介紹了Nett中的心跳機制與斷線重連詳解,我們以客戶端發(fā)送心跳為例,平時我們的心跳實現(xiàn)方式可能是搞個定時器,定時發(fā)送是吧,但是在Netty中卻不一樣,心跳被稱為空閑檢測,需要的朋友可以參考下
    2023-12-12
  • Nginx+SpringCloud Gateway搭建項目訪問環(huán)境

    Nginx+SpringCloud Gateway搭建項目訪問環(huán)境

    本文主要介紹了Nginx+SpringCloud Gateway搭建項目訪問環(huán)境,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • Java連接MySQL數(shù)據(jù)庫實例

    Java連接MySQL數(shù)據(jù)庫實例

    這篇文章介紹了Java連接MySQL數(shù)據(jù)庫實例的方法,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-04-04
  • Java微信公眾平臺開發(fā)(8) 多媒體消息回復

    Java微信公眾平臺開發(fā)(8) 多媒體消息回復

    這篇文章主要為大家詳細介紹了Java微信公眾平臺開發(fā)第八步,微信多媒體消息回復,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • JavaWeb實戰(zhàn)之開發(fā)網上購物系統(tǒng)(超詳細)

    JavaWeb實戰(zhàn)之開發(fā)網上購物系統(tǒng)(超詳細)

    這篇文章主要介紹了JavaWeb實戰(zhàn)之開發(fā)網上購物系統(tǒng)(超詳細),文中有非常詳細的代碼示例,對正在學習java的小伙伴們有很好的幫助,需要的朋友可以參考下
    2021-04-04
  • java.lang.String類的使用

    java.lang.String類的使用

    這篇文章主要介紹了java.lang.String類的使用,以及字符串的相關知識,需要了解相關知識的小伙伴可以參考該篇文章
    2021-08-08
  • java?Web實現(xiàn)用戶登錄功能圖文教程

    java?Web實現(xiàn)用戶登錄功能圖文教程

    這篇文章主要給大家介紹了關于java?Web實現(xiàn)用戶登錄功能的相關資料,在開發(fā)Web應用程序中,用戶登錄是一個常見的功能,文中通過代碼以及圖文介紹的非常詳細,需要的朋友可以參考下
    2023-10-10
  • Java中AIO、BIO、NIO應用場景及區(qū)別

    Java中AIO、BIO、NIO應用場景及區(qū)別

    本文主要介紹了Java中AIO、BIO、NIO應用場景及區(qū)別,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-06-06
  • Spring Boot快速實現(xiàn) IP地址解析的示例詳解

    Spring Boot快速實現(xiàn) IP地址解析的示例詳解

    這篇文章主要介紹了Spring Boot快速實現(xiàn)IP地址解析,本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-08-08
  • SpringBoot?如何將項目打包成?jar?包

    SpringBoot?如何將項目打包成?jar?包

    這篇文章主要介紹了SpringBoot如何將項目打包成jar包,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-08-08

最新評論

蒲城县| 丰都县| 汕尾市| 苍山县| 武穴市| 思茅市| 陆河县| 乃东县| 蒙自县| 郑州市| 历史| 轮台县| 河北区| 都江堰市| 那曲县| 华坪县| 石首市| 墨脱县| 平山县| 金昌市| 铜陵市| 秦安县| 西乌珠穆沁旗| 原阳县| 当涂县| 泾川县| 铜山县| 阜新市| 白城市| 古交市| 松桃| 久治县| 腾冲县| 温泉县| 蚌埠市| 嘉祥县| 德昌县| 赤壁市| 山西省| 兴山县| 子洲县|