使用 zip4j 解压 zip 文件时出现 "negative time" 异常
Getting "negative time" exception when unpacking zip file with zip4j
我正在使用 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
的使用无关。
zip4j
自 2013
以来就没有得到维护,所以如果它有一些错误我不会感到惊讶,但是没有另一个没有样板的更强大的 zip
库除了 JDK
那个。但是,我需要密码保护的 zip 文件支持和 that isn't supported by the JDK.
安装 JDK 11
并将其用于 运行 应用程序并未解决问题,但值得一试。
经过更多研究,我发现 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>
我发现问题是当前时间和最新文件修改时间。格式不匹配。你可以用这个检查:
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()));
然后在 区域设置 中设置格式 >> 区域格式 >> 英语(美国)
我正在使用 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
的使用无关。
zip4j
自 2013
以来就没有得到维护,所以如果它有一些错误我不会感到惊讶,但是没有另一个没有样板的更强大的 zip
库除了 JDK
那个。但是,我需要密码保护的 zip 文件支持和 that isn't supported by the JDK.
安装 JDK 11
并将其用于 运行 应用程序并未解决问题,但值得一试。
经过更多研究,我发现 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>
我发现问题是当前时间和最新文件修改时间。格式不匹配。你可以用这个检查:
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()));
然后在 区域设置 中设置格式 >> 区域格式 >> 英语(美国)