简体   繁体   English

提取 ZIP 文件失败 - 里面没有文件,提取后扩展名为 .zip25

[英]Extracted ZIP file failed - No files inside, and having .zip25 extension after extract

I was trying to extract the ZIP file from my Linux, I'm able to extract it, but the expected output is failing/wrong.我试图从我的 Linux 中提取 ZIP 文件,我能够提取它,但预期的 output 失败/错误。 The extract file suddenly has no files inside and the folder extracted has.zip25 extension.解压文件里面突然没有文件了,解压后的文件夹扩展名为.zip25。 I searched on this, and there is saying that it is corrupted.我搜索了一下,据说它已损坏。 However, I don't think it is corrupted because I am able to open and extract the zip files perfectly in local (Windows directory).但是,我不认为它已损坏,因为我能够在本地(Windows 目录)中完美地打开和提取 zip 文件。

Example:例子:

Zip file: FolderZip.zip Zip 文件:FolderZip.zip

After extract: FolderZip.zip25 (Note: This is already extracted but still has.zip25 extension, also the files inside are missing).解压后:FolderZip.zip25(注意:这个已经解压了,但是扩展名还是.zip25,里面的文件也不见了)。

Below is my code, I've worked on this for almost a month, but still can't figure it out.下面是我的代码,我已经为此工作了将近一个月,但仍然无法弄清楚。 Can someone help me to figure out what did I do wrong?有人可以帮我弄清楚我做错了什么吗?

public void unZipFolder(String zipFile, String outputFolder){
        byte[] buffer = new byte[1024];

        System.out.println("ZipFileLocation: " + zipFile);
        LOG.info(" ZipFileLocation: " + zipFile);

        File folder = new File(outputFolder);
        if(!folder.exists())folder.mkdirs();

        try{
            FileInputStream fis = new FileInputStream(zipFile);
            ZipInputStream zis = new ZipInputStream(fis);
            ZipEntry ze = zis.getNextEntry();
            
            while(ze != null) {
                new File(folder.getParent()).mkdirs();
                FileOutputStream fos = new FileOutputStream(folder);
                File newFile = new File(outputFolder + FilenameUtils.indexOfLastSeparator(ze.getName()));
                                
                if (ze.isDirectory()) {
                    if (!newFile.isDirectory() && !newFile.mkdirs()) {
                        throw new IOException("Failed to create directory " + newFile);
                    }else if(ze.isDirectory()){
                        newFile.mkdirs();
                        continue;
                    }else{
                        int len;
                        while ((len = zis.read(buffer)) >= 0) {
                            fos.write(buffer, 0, len);
                        }
                        
                        System.out.println("File Unzip: " + newFile);
                        LOG.info(" File Unzip: " + newFile);
                        newFile.mkdirs();
                        fos.close();
                        zis.closeEntry();
                        ze = zis.getNextEntry();
                    }
                }    
                
                boolean result = Files.deleteIfExists(Paths.get(zipFile));
                if (result) {
                    System.out.println("ZipFile is deleted....");
                } else {
                    System.out.println("Unable to delete the file.....");
              }
            }
            zis.closeEntry();
            zis.close();
            fis.close();
         }catch(IOException ex){
            ex.printStackTrace();
     }
}

I'd love to be able to tell you exactly what's wrong with your code, but FileOutputStream fos = new FileOutputStream(folder);我很想能够准确地告诉您您的代码有什么问题,但是FileOutputStream fos = new FileOutputStream(folder); throws an exception because, well, folder is, a directory, so you can't write to it.抛出一个异常,因为好吧, folder是一个目录,所以你不能写入它。

I'm also scratching my head over what your expecting new File(folder.getParent()).mkdirs();我也在摸不着头脑你期待什么new File(folder.getParent()).mkdirs(); to do.去做。

I basically threw out your code and started again with...我基本上扔掉了你的代码并重新开始......

public void unZipFolder(File zipFile, File outputFolder) throws IOException {
    byte[] buffer = new byte[1024];

    System.out.println("ZipFileLocation: " + zipFile);
    System.out.println("outputFolder = " + outputFolder);

    if (!outputFolder.exists() && !outputFolder.mkdirs()) {
        throw new IOException("Unable to create output folder: " + outputFolder);
    } else if (outputFolder.exists() && !outputFolder.isDirectory()) {
        throw new IOException("Output is not a directory: " + outputFolder);
    }

    try (ZipFile zipper = new ZipFile(zipFile)) {
        Enumeration<? extends ZipEntry> entries = zipper.entries();
        while (entries.hasMoreElements()) {
            ZipEntry ze = entries.nextElement();
            File destination = new File(outputFolder, ze.getName());
            if (ze.isDirectory()) {
                if (!destination.exists() && !destination.mkdirs()) {
                    throw new IOException("Could not create directory: " + destination);
                }
            } else {
                System.out.println("Writing " + destination);
                try (InputStream is = zipper.getInputStream(ze); FileOutputStream fos = new FileOutputStream(destination)) {
                    // You could use is.transferTo(fos) here but I'm a grump old coder
                    byte[] bytes = new byte[1024 * 4];
                    int bytesRead = -1;
                    while ((bytesRead = is.read(bytes)) != -1) {
                        fos.write(bytes, 0, bytesRead);
                    }
                }
            }
        }
    }
}

Now, what's important to know about this is, it expects the directory contents of the zip files to be relative (ie no root directory information).现在,需要了解的重要一点是,它希望 zip 文件的目录内容是相对的(即没有根目录信息)。 If your zip file does contain root directory information (ie C:/... or /... ), then you're going to need to clean that up yourself.如果您的 zip 文件确实包含根目录信息(即C:/.../... ),那么您将需要自己清理它。

Now, if you have trouble with this, I would suggest commenting out the "extraction" portion of the code and placing in more System.out.println statements现在,如果您对此有困难,我建议注释掉代码的“提取”部分并放入更多System.out.println语句

transferTo

After reading through the code for transferTo , it's basically doing the same thing that the code example above is doing - so, if you wanted to reduce the code complexity (and reduce the risk of possible bugs), you could use it - been some what old school, I'd probably still do it the "old way" in order to provide support for progress monitoring of some kind - but that's beyond the scope of the question.在阅读了transferTo的代码之后,它基本上做了与上面的代码示例相同的事情 - 所以,如果你想降低代码复杂性(并降低可能出现错误的风险),你可以使用它 - 是一些什么守旧派,我可能仍然会以“旧方式”进行操作,以便为某种进度监控提供支持 - 但这超出了问题的 scope 范围。

"Security issues" “安全问题”

This ones a little harder to tie down, as no solution is 100% safe.这有点难以约束,因为没有解决方案是 100% 安全的。

I modified the above code to use something like...我修改了上面的代码以使用类似...

Path parent = outputFolder.toPath().toAbsolutePath();
String name = "../" + ze.getName();
Path child = parent.resolveSibling(new File(outputFolder, name).toPath());

And this ended up throwing a NoSuchFileException , so, at least you could "fail fast", assuming that's what you want.这最终抛出了一个NoSuchFileException ,所以,至少你可以“快速失败”,假设这就是你想要的。

You might also consider removing .. , leading / or leading path specifications in an attempt to make the path "relative", but that could become complicated as something like somePath/../file could still be valid within your use case.您也可以考虑删除.. 、前导/或前导路径规范,以尝试使路径“相对”,但这可能会变得复杂,因为somePath/../file之类的内容在您的用例中仍然有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM