【问题标题】:Getting "negative time" exception when unpacking zip file with zip4j使用 zip4j 解压 zip 文件时出现“负时间”异常
【发布时间】:2018-11-12 12:06:14
【问题描述】:

我正在使用zip4j 提取zip 文件。对于许多用户来说,这可以正常工作,但 Windows 8 用户遇到以下异常:

net.lingala.zip4j.exception.ZipException: net.lingala.zip4j.exception.ZipException: java.lang.IllegalArgumentException: Negative time
    at net.lingala.zip4j.unzip.Unzip.initExtractFile(Unzip.java:163)
    at net.lingala.zip4j.unzip.Unzip.initExtractAll(Unzip.java:83)
    at net.lingala.zip4j.unzip.Unzip.extractAll(Unzip.java:73)
    at net.lingala.zip4j.core.ZipFile.extractAll(ZipFile.java:488)
    at net.lingala.zip4j.core.ZipFile.extractAll(ZipFile.java:451)
    ...

负时间似乎是由file on the file system having a negative time and/or by a JVM bug 引起的。有谁知道如何解决这个问题,因为这很奇怪,并且与我假设的 API 的使用无关。

zip4j2013 以来一直没有维护,所以如果它有一些错误,我不会感到惊讶,但除了JDK 之外,没有另一个功能更强大的zip 库没有样板。但是,我需要受密码保护的 zip 文件支持和that isn't supported by the JDK

安装JDK 11 并使用它来运行应用程序并不能解决问题,但值得一试。

【问题讨论】:

    标签: java zip zip4j


    【解决方案1】:

    经过一番研究,我找到了7-Zip-JBinding

    <dependency>
        <groupId>net.sf.sevenzipjbinding</groupId>
        <artifactId>sevenzipjbinding</artifactId>
        <version>LATEST</version>
    </dependency>
    <dependency>
        <groupId>net.sf.sevenzipjbinding</groupId>
        <artifactId>sevenzipjbinding-all-platforms</artifactId>
        <version>LATEST</version>
    </dependency>
    

    以下代码可用于提取受密码保护的 zip 文件:

    public static void unzipUsing7Zip(String zipFilePath,
                                       String destinationDirectory,
                                       String password) throws IOException
    {
        try (val randomAccessFile = new RandomAccessFile(zipFilePath, "r");
             val randomAccessFileInStream = new RandomAccessFileInStream(randomAccessFile);
             val inArchive = openInArchive(null, randomAccessFileInStream))
        {
            val simpleInArchive = inArchive.getSimpleInterface();
            val archiveItems = simpleInArchive.getArchiveItems();
    
            for (val archiveItem : archiveItems)
            {
                if (!archiveItem.isFolder())
                {
                    val archiveItemPath = archiveItem.getPath();
                    val targetFilePath = destinationDirectory + separator + archiveItemPath;
    
                    try (val fileOutputStream = new FileOutputStream(targetFilePath))
                    {
                        archiveItem.extractSlow(data ->
                        {
                            try
                            {
                                if (archiveItemPath.indexOf(separator) > 0)
                                {
                                    // Create parent folder(s)
                                    val lastSeparatorIndex = archiveItemPath.lastIndexOf(separator);
                                    val path = destinationDirectory + separator + archiveItemPath.substring(0, lastSeparatorIndex);
                                    createDirectories(Paths.get(path));
                                }
    
                                fileOutputStream.write(data);
                            } catch (Exception exception)
                            {
                                exception.printStackTrace();
                            }
    
                            return data.length;
                        }, password);
                    }
                }
            }
        }
    }
    

    基于here,但经过清理并添加了通过FileOutputStream 提取的真实文件代码。

    补充说明:val当然来自lombok

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>LATEST</version>
        <scope>provided</scope>
    </dependency>
    

    【讨论】:

      【解决方案2】:

      我发现问题出在当前时间最新文件修改时间。格式不匹配。你可以用这个检查:

      DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");  
      LocalDateTime now = LocalDateTime.now();  
      System.out.println(dtf.format(now));  
      
      File file = new File("folder/source.zip");
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
      System.out.println(sdf.format(file.lastModified()));
      

      然后在区域设置 >> 区域格式 >> 英语(美国)

      中设置您的格式

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-27
        • 2020-04-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-28
        相关资源
        最近更新 更多