Java NIO Zip 文件系统相当于 java.util.zip.ZipEntry 中的 setMethod()

标签 java zip compression nio

我有一些现有代码可以创建 Epub 2 格式的 zip 文件,它可以正常工作。

在尝试更新我的代码以支持 Epub 3 格式时,我想我会尝试使用 Java NIO Zip 文件系统而不是 java.util.zip.ZipFile。除了一件小元素,我几乎就在那里。

Epub 格式需要一个 20 字节的 mimetype 文件,必须以未压缩的形式放入 zip 中。 java.util.zip.ZipEntry API 提供了setMethod(ZipEntry.STORED) 来实现这一点。

我在 Java NIO FileSystem API 文档中找不到对此的任何引用。是否有等效于 ZipEntry.setMethod() 的方法?

编辑 1

好的,所以我看到了如何显示属性,感谢您提供的示例,但是我找不到任何关于如何创建属性的文档,例如 (zip:method,0 ),甚至在 Oracle 自己的 oracle 上。在我看来,Java 7 中的 NIO 增强功能只记录了大约 20%。属性 api 文档非常稀疏,尤其是如何创建属性。

我开始觉得 NIO Zip 文件系统可能不是 java.util.zip 的改进,需要更多代码才能实现相同的结果。

编辑 2

我尝试了以下方法:

String contents = "application/epub+zip"; /* contents of mimetype file */
Map<String, String> map = new HashMap<>();
map.put("create", "true");

Path zipPath = Paths.get("zipfstest.zip");
Files.deleteIfExists(zipPath);

URI fileUri = zipPath.toUri(); // here
URI zipUri = new URI("jar:" + fileUri.getScheme(), fileUri.getPath(), null);

try (FileSystem zipfs = FileSystems.newFileSystem(zipUri, map)) {
    Path pathInZip = zipfs.getPath("mimetype");
    Files.createFile(pathInZip, new ZipFileAttribute<Integer>("zip:method", 0));
    byte[] bytes = contents.getBytes();
    Files.write(pathInZip, bytes, StandardOpenOption.WRITE);
    }

ZipFileAttribute 类是属性接口(interface)的最小实现。我可以发布它,但它只是一个键值对(名称,值)

此代码成功创建了 zipFile,但是当我使用 7zip 打开 zipFile 时,我看到 mimetype 文件以 DEFLATED (8) 的形式存储在 zip 中,而不是我需要的 STORED (0)。所以问题是,我如何正确编码该属性,以便它存储为 STORED。

最佳答案

这没有很好的文档记录,但 JDK 的 zip 文件系统提供程序支持名为 zipFileAttributeView

这是我的 zip 中的代码:

public static void main(final String... args)
    throws IOException
{
    final Path zip = Paths.get("/home/fge/t.zip");
    final Map<String, ?> env = Collections.singletonMap("readonly", "true");
    final URI uri = URI.create("jar:" + zip.toUri());

    try (
        final FileSystem fs = FileSystems.newFileSystem(uri, env);
    ) {
        final Path slash = fs.getPath("/");
        Files.readAttributes(slash, "zip:*").forEach( (key, val) -> {
            System.out.println("Attribute name: " + key);
            System.out.printf("Value: %s (class: %s)\n", val,
                val != null ? val.getClass(): "N/A");
        });
    }
}

输出:

Attribute name: size
Value: 0 (class: class java.lang.Long)
Attribute name: creationTime
Value: null (class: N/A)
Attribute name: lastAccessTime
Value: null (class: N/A)
Attribute name: lastModifiedTime
Value: 1969-12-31T23:59:59.999Z (class: class java.nio.file.attribute.FileTime)
Attribute name: isDirectory
Value: true (class: class java.lang.Boolean)
Attribute name: isRegularFile
Value: false (class: class java.lang.Boolean)
Attribute name: isSymbolicLink
Value: false (class: class java.lang.Boolean)
Attribute name: isOther
Value: false (class: class java.lang.Boolean)
Attribute name: fileKey
Value: null (class: N/A)
Attribute name: compressedSize
Value: 0 (class: class java.lang.Long)
Attribute name: crc
Value: 0 (class: class java.lang.Long)
Attribute name: method
Value: 0 (class: class java.lang.Integer)

看起来“zip:method”属性就是您想要的。

所以,如果你想改变方法,如果你有一个 Path 到你的 zip 文件系统,看起来你可以做(​​未经测试!):

Files.setAttribute(thePath, "zip:method", ZipEntry.DEFLATED);

关于Java NIO Zip 文件系统相当于 java.util.zip.ZipEntry 中的 setMethod(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28239621/

相关文章:

java - 使用我的自签名证书创建一个 KeyStore 实例

java - 解压里面有大量小文件的文件

c# - 使用 .NET 4.5 解压缩受密码保护的 ZIP 文件

list - Powershell脚本列出目录中的Zip文件及其大小

python - 使用 Python 将很长的二进制字符串编码为可恢复的简单形式的最佳方法?

c# - 如何从 C# .NET 4.5 中的 zip 存档中提取特定目录?

java - 在 HashSet 中搜索时如何使用正则表达式

java - for 循环的内存占用

java - JSF + RichFaces 在我的页面中提供 HTTP 状态 404

audio - Audible 如何将 24 小时长的音频文件(FLAC、Opus、AA 和 AAC)实现 300MB 文件大小?