猿问

Java ZipFileSystem 在遍历时不保留物理顺序

让我们考虑一个非常简单的 Java 片段:


String pathUriStr = Paths.get(args[0]).toUri().toASCIIString();

URI zipUri = URI.create("jar:" + pathUriStr);


FileSystem zip = null;

try {

  zip = FileSystems.newFileSystem(zipUri, Collections.emptyMap());

} catch (IOException e1) {

  // TODO Auto-generated catch block

  e1.printStackTrace();

}

Path zipRoot = zip.getPath("/");


System.out.println("ZipFileSystem:");

FileVisitor<Path> visitor = new SimpleFileVisitor<Path>() {


  @Override

  public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)

      throws IOException {

    System.out.println(file);

    return super.visitFile(file, attrs);

  }


  @Override

  public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)

      throws IOException {

    System.out.println(dir);

    return super.preVisitDirectory(dir, attrs);

  }


};

try {

  Files.walkFileTree(zipRoot, visitor);

} catch (IOException e) {

  // TODO Auto-generated catch block

  e.printStackTrace();

}

输出是:


ZipFileSystem:

/

/images

/images/ant_logo_large.gif

/org

/org/apache

...

/META-INF

/META-INF/LICENSE.txt

/META-INF/MANIFEST.MF

对 `ZipInputStream 做同样的事情:


System.out.println("ZipInputStream:");

try (InputStream is = Files.newInputStream(Paths.get(args[0]), StandardOpenOption.READ);

     ZipInputStream zipIs = new ZipInputStream(is)) {

  ZipEntry entry = null;


  while((entry = zipIs.getNextEntry()) != null) {

    System.out.println(entry);

    zipIs.closeEntry();

  }

} catch (IOException e) {

  // TODO Auto-generated catch block

  e.printStackTrace();

}

给我:


ZipInputStream:

META-INF/

META-INF/MANIFEST.MF

org/

org/apache/

...

META-INF/LICENSE.txt

images/

images/ant_logo_large.gif


虽然这首先看起来不像是一个问题,但它是一个巨大的问题,因为这个 JAR 将被拒绝,因为根据 JAR 规范META-INF/,它META-INF/MANIFEST.MF不是第一个条目。


我的用例非常相似,我想使用 ZIP 文件,并希望要求一些条目成为第一个快速验证输入的条目,而不必寻找到文件的末尾。


所有测试均使用 Java 8、10 和 11-ea。


那么问题来了,为什么 Zip 文件系统不保留流中出现的顺序呢?


隔江千里
浏览 262回答 1
1回答

MMMHUHU

ZipFileSystem是底层 zip 文件的抽象,允许您以与FileSystem 的任何其他实现相同的方式处理它。从根开始,让它在您期望的常规树状结构中工作是非常有意义的/。如果您想轻松地从/向 zip 复制文件,这非常棒,就像您在常规目录之间所做的那样。这样做的缺点是您对 zip 本身失去了一些控制。ZipInputStream是一个更低级别的抽象,您可以在其中控制结构和其他 zip 文件特定的内容。缺点是您可能需要编写更多代码。示例:您想将文件从一个 zip 复制或移动到另一个:有了ZipFileSystem这相当于移动从一个目录复制到另一个文件中,代码适用于任何执行FileSystem。使用 zip 流,您必须手动处理源 zip 文件,找到正确的条目,删除条目,然后将其添加到第二个 zip 文件中,并在此过程中重写文件。这是 1 行代码与几行、循环和其他样板。SoZipFileSystem为您提供了更高抽象的好处,但也有缺点,例如内存使用、对 zip 文件细节的控制较少等。ZipXXXStream为您提供 zip 的低级视图,处理 zip 条目和其他您并不总是需要的内部细节。
随时随地看视频慕课网APP

相关分类

Java
我要回答