Java NIO Zip Filesystem相当于java.util.zip.ZipEntry中的setMethod()

时间:2015-01-30 15:50:15

标签: 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 doc属性非常稀疏,特别是如何创建属性。

我开始得到的感觉是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类是属性接口的最小实现。我可以发布它,但它只是一个键值对(名称,值)

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

3 个答案:

答案 0 :(得分:2)

这个文档没有很好的记录,但JDK的zip文件系统提供程序支持名为FileAttributeView的{​​{1}}。

以下是我的拉链代码:

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

外观就像“zip:method”属性一样。

所以,如果你想改变方法,如果你的zip文件系统有一个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) ,看起来你可以这样做(UNTESTED!):

Path

答案 1 :(得分:1)

根据下面非常有趣的回复,我重读了所有可用的API文档,并在设置属性时尝试了各种猜测。我在两者上画了一个空白。我不得不得出结论,这个功能最多没有文档记录,甚至可能在Java NIO中不可用。因此,任何想要以EPUB格式创建文件的人都必须继续使用旧的基于ZipFile的API。另一种方法是使用用ZipFile或其他语言创建的shell zip,然后切换到NIO。这两个选项都是 - 我怎么说 - 有点不优雅。我认为java.io.File的目的是随着时间的推移逐渐被弃用。

答案 2 :(得分:0)

在Java8中,无法设置压缩方法(在OpenJDK中,其他供应商可能具有不同的实现),因为它是硬编码的。在Java11中,未记录jdk.zipfs模块,但是通过查看源代码,noCompression中出现了一个新选项jdk.nio.zipfs.ZipFileSystem。自Java14起,这些选项终于被完整记录:https://docs.oracle.com/en/java/javase/14/docs/api/jdk.zipfs/module-summary.html

FileSystems.newFileSystem(URI uri, Map<String,?> env)可用于向文件系统添加其他选项。

例如(Java11):

try (FileSystem zipFs = FileSystems.newFileSystem(
    new URI("jar:file:///tmp/test.zip"),
    Map.of("noCompression", true, "create", true))) {
  Path testFile = zipFs.getPath("/test.txt");
  try (OutputStream os = Files.newOutputStream(testFile)) {
    os.write("Testing uncompressed text".getBytes(StandardCharsets.UTF_8));
  }
}

将创建一个压缩文件/tmp/test.zip,其中一个条目/test.txt的长度为25个字节,并且未压缩。

Java14添加了带有值compressionMethodSTORED的新选项DEFLATED,但支持noCompression选项以实现向后兼容。