如何在java中提取zip文件中的特定文件

问题描述 投票:0回答:6

我需要在系统中向客户提供zip文件的视图,并允许客户下载所选文件。

  1. 解析zip文件并显示在网页上。并记住后端中的每个 zipentry 位置(例如 file1 从字节 100 宽度长度 1024 字节开始)。
  2. 当客户点击下载按钮时,下载指定文件。

现在我已经记住了所有zipentry位置,但是有没有java zip工具可以解压缩zip文件的指定位置? API 就像 unzip(file, longentryStart, longentryLength);

java zip
6个回答
23
投票

使用 Java 7 的 NIO2 可以在不弄乱字节数组或输入流的情况下完成此操作:

public void extractFile(Path zipFile, String fileName, Path outputFile) throws IOException {
    // Wrap the file system in a try-with-resources statement
    // to auto-close it when finished and prevent a memory leak
    try (FileSystem fileSystem = FileSystems.newFileSystem(zipFile, null)) {
        Path fileToExtract = fileSystem.getPath(fileName);
        Files.copy(fileToExtract, outputFile);
    }
}

13
投票

您可以使用以下代码从 zip 中提取特定文件:-

public static void main(String[] args) throws Exception{
        String fileToBeExtracted="fileName";
        String zipPackage="zip_name_with_full_path";
        OutputStream out = new FileOutputStream(fileToBeExtracted);
        FileInputStream fileInputStream = new FileInputStream(zipPackage);
        BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream );
        ZipInputStream zin = new ZipInputStream(bufferedInputStream);
        ZipEntry ze = null;
        while ((ze = zin.getNextEntry()) != null) {
            if (ze.getName().equals(fileToBeExtracted)) {
                byte[] buffer = new byte[9000];
                int len;
                while ((len = zin.read(buffer)) != -1) {
                    out.write(buffer, 0, len);
                }
                out.close();
                break;
            }
        }
        zin.close();

    }

另请参阅此链接:如何从远程存档文件中提取单个文件?


8
投票

你可以这样尝试:

ZipFile zf = new ZipFile(file);
try {
  InputStream in = zf.getInputStream(zf.getEntry("file.txt"));
  // ... read from 'in' as normal
} finally {
  zf.close();
}

我还没有尝试过,但在 Java 7 ZipFileSystem 中你可以尝试这样从 zip 文件中提取 file.TXT 文件。

Path zipfile = Paths.get("/samples/ziptest.zip");
FileSystem fs = FileSystems.newFileSystem(zipfile, env, null);
final Path root = fs.getPath("/file.TXT");

0
投票

要使用 FileSystems.newFileSystem,您需要使用 URI.create 来创建第一个参数

您需要指定正确的协议。 “罐子:文件:”

另外:你需要一个具有以下属性的 Map() :

map.put("create","true"); (or "false" to extract)
extract("/tmp","photos.zip","tiger.png",map)

void extract(String path, String zip, String entry, Map<String,String> map){
        try (FileSystem fileSystem = FileSystems.newFileSystem(URI.create("jar:file:"+ path + "/" + zip), map)) {
           Path fileToExtract = fileSystem.getPath(entry);
           Path fileOutZip = Paths.get(path + "/unzipped_" + entry );
           Files.copy(fileToExtract, fileOutZip);

}
}

0
投票

所以我遇到了一个相关问题,但在这里没有得到完全解答。如果我在流式传输下载时只有

ZipInputStream
,如何仅提取多个特定文件。这让我抓狂,因为如果您不想将它们全部解压,那么如何获取输入流中的下一个条目并不明显。答案是递归函数。

  static void caller() {
      // res.body() is from java's http client, but basically wherever you get the inputstream that is a zip
      try (var is = new ZipInputStream(res.body())) {
        recurseExtract(is, is.getNextEntry(), dir);
      }
  }

  static void recurseExtract(ZipInputStream is, ZipEntry entry, Path dir) throws IOException {
    if (entry == null) {
      return;
    }
    if (shouldExtract(entry.getName())) {
      var path = Path.of(entry.getName());
      if (path.getNameCount() > 1) {
        if (entry.isDirectory() ) {
          Files.createDirectory(dir.resolve(path));
        }
        else {
          System.out.println("Extracting " + dir.resolve(noRoot));
          Files.copy(is, dir.resolve(noRoot));
        }
      }
    }
    is.closeEntry(); // not certain this is necessary
    recurseExtract(is, is.getNextEntry(), dir);
  }

  static boolean shouldExtract(String entry) {
    // check for ".." to avoid zip slip security vulnerability
    return ! entry.contains(".."); // put other filtering here, but check for the .. too somewhere
  }

-1
投票

我处理过一个案例:
步骤1:我在指定目录中有zip文件需要解压
第2步:将解压后的文件(一个zip文件中的多个文件)存储在指定目录中)(注意:清理要移动解压文件的目标目录)。

这是对我有用的代码:

public String unZip(String zipFilePath, String destDirectory, String afilename) {
        
        String efilename; String[] files; String unzipfilePath; String[] oldFiles;
        File destDir = new File(destDirectory);
        if (destDir.isDirectory()) {
            oldFiles = destDir.list();
               for (int k = 0; k < oldFiles.length; k++) {
                   File oFiles = new File(oldFiles[k]);
                   logMessage("Old file name in the unziped folder is "+oFiles );
                   oFiles.delete();
                }
                
            }
        if (!destDir.exists()) {
            destDir.mkdir();
        }
        
         ZipInputStream zipIn;
        try {
            zipIn = new ZipInputStream(new FileInputStream(zipFilePath));

            ZipEntry entry = zipIn.getNextEntry();
            // iterates over entries in the zip file
            while (entry != null) {
                
                unzipfilePath = destDirectory + File.separator + entry.getName();
                 
                if (!entry.isDirectory()) {
                    // if the entry is a file, extracts it
                    extractFile(zipIn, unzipfilePath);
                     logMessage(" File copied to Unziped folder is " +unzipfilePath);
                } else {
                    // if the entry is a directory, make the directory
                    File dir = new File(unzipfilePath);
                    dir.mkdir();
                }
                zipIn.closeEntry();
                entry = zipIn.getNextEntry();
            }
            zipIn.close(); 
            
            // check for filename in the unzipped folder
            
            File dest = new File(destDirectory);
            files = dest.list();
            int flag = 0;
            if (files == null) {
                logMessage("Empty directory.");
            }
            else {
      
                // Linear search in the array forf expected file name 
                for (int i = 0; i < files.length; i++) {
                    efilename = files[i];
                    if (efilename.equals(afilename))
                        logMessage(efilename + " Expected File found in Unziped files folder");
                        flag = 1;
                        Assert.assertNotNull(efilename);
                       
                }
                    
            }
            
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        return efilename;
    }
© www.soinside.com 2019 - 2024. All rights reserved.