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

15
我需要在系统中向客户提供zip文件的视图,让客户可以下载所选的文件。
  1. 解析zip文件并显示在网页上,并在后台记住每个zipentry的位置(例如,文件1从字节100开始,长度为1024字节)。
  2. 当客户单击下载按钮时,下载指定的文件。
现在我已经记住了所有的zipentry位置,但是否有Java zip工具可以解压缩zip文件的特定位置?API就像unzip(file,long entryStart,long entryLength)。

阅读此链接:http://www.mkyong.com/java/how-to-decompress-files-from-a-zip-file/ - Kashyap Kansara
谢谢,但这不是我想要的。 - Mr rain
5个回答

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();

    }

还可以参考此链接:如何从远程存档文件中提取单个文件?


2
它的表现很好,但仅适用于一种情况,即在每个条目头中保存了压缩大小和原始条目大小。但是,某些zip文件中没有保存这些信息,在这种情况下,zin.getNextEntry()将读取先前条目的数据以到达下一个条目,而不是寻找下一个条目,因此它会执行得很慢。 - Mr rain

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创建第一个参数。
您需要指定正确的协议。 "jar:file:"
另外:您需要一个具有属性的Map<String,String>()。
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

我曾经处理过一个案例,其中包括以下步骤:
第一步:我有一个压缩文件在指定目录中需要解压缩
第二步:将解压后的文件(一个压缩文件中可能有多个文件)存储到指定目录中(注意:清空你想要移动解压后文件的目标目录)。

这是对我有效的代码:

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;
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接