首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >把一个罐子的FileSystems放进另一个罐子

把一个罐子的FileSystems放进另一个罐子
EN

Stack Overflow用户
提问于 2014-10-06 15:26:06
回答 3查看 4.7K关注 0票数 5

这就是我想做的:

代码语言:javascript
复制
FileSystem fs1 = FileSystems.newFileSystem(Paths.get("f1.jar"), null);
FileSystem fs2 = FileSystems.newFileSystem(fs1.getPath("/f2.jar"), null);

但是我在第二行中得到了一个由FileSystems.newFileSystem()抛出的FileSystems.newFileSystem()

我做错了什么?

谢谢!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-10-06 16:11:51

首先不得不提取嵌套的jar。

编辑:在甲骨文论坛上的答案,没有给出为什么你必须首先提取jar的明确理由。

这里引用从… Rajendra Gutupalli的博客(com.sun.nio.zipfs的作者):

让我们假设在Zip中嵌套了一个Jar文件。下面的程序打印MANIFEST.MF文件的内容,该文件位于嵌套的jarCompress1.jar 1.jar文件中。 导入java.io.BufferedInputStream;导入java.nio.file.*;导入java.util.HashMap;导入java.util.Map;公共类ReadEntry { public静态void (String.( args)抛出异常{ Path zipfile = Path.get("c:/zips/zip1.zip");Map env =新HashMap();FileSystem manager = FileSystems.newFileSystem(zipfile,env,null);path = Path System.out.println(“读取输入流”);BufferedInputStream bis =新BufferedInputStream(path.newInputStream();int ch = -1;时间((ch = bis.read()) != -1) { System.out.print((char) ch);}}

和另一个

这里要注意的一点是,zip文件路径可以扩展到文件路径名称中的嵌套zip或jars。例如,/home/userA/zipfile.zip/DirA/dirB/jarFile.jar/META-INF/MANIFEST.MF访问Zip文件“/home/userA/zipfile.zip”中的jar文件“jarFile.jar”。

我无法复制声称的行为。下一个代码:

代码语言:javascript
复制
try (FileSystem fs1 = FileSystems.newFileSystem(Paths.get("f1.zip"), null)) {
    Path path = fs1.getPath("/f2.zip/test.txt");
    Files.lines(path).forEach(System.out::println);
}

给予例外

代码语言:javascript
复制
Exception in thread "main" java.nio.file.NoSuchFileException: f2.zip/test.txt
  at com.sun.nio.zipfs.ZipFileSystem.newInputStream(ZipFileSystem.java:544)
  at com.sun.nio.zipfs.ZipPath.newInputStream(ZipPath.java:645)
  at com.sun.nio.zipfs.ZipFileSystemProvider.newInputStream(ZipFileSystemProvider.java:278)
  at java.nio.file.Files.newInputStream(Files.java:152)
  at java.nio.file.Files.newBufferedReader(Files.java:2781)
  at java.nio.file.Files.lines(Files.java:3741)
  at java.nio.file.Files.lines(Files.java:3782)

可能有人会确认这是一个bug,或者指出了我代码中的错误。

同时回到你原来的问题。您不能在zip(jar)中创建FileSystem,因为没有FileSystemProvider (查看newFileSystem方法的源代码),它可以从ZipPath创建FileSystem实例。因此,您必须选择提取from外部zip或编写您自己的FileSystemProvider实现。

票数 1
EN

Stack Overflow用户

发布于 2021-07-17 14:39:42

给定像: jar:file:/console/console.jar!/BOOT-INF/lib/generator.jar!/generator/static/这样的jarfile URI

我编写了以下方法来递归提取jars并返回所有文件系统:

代码语言:javascript
复制
private FileSystem getNestedFileSystems(URI generatorAssets) throws IOException {
    String[] jarFiles = generatorAssets.toString().split("!");
    URI rootJarUri = URI.create(jarFiles[0]);
    FileSystem currentFs;
    try {
        currentFs = FileSystems.getFileSystem(rootJarUri);
    } catch (FileSystemNotFoundException fsnf) {
        currentFs = FileSystems.newFileSystem(rootJarUri, Map.of("create", "true"));
    }
    Path currentJar = null;
    if (jarFiles.length > 2) {
        for (int i = 1; i < (jarFiles.length - 1); i++) {
            Path nestedJar = currentFs.getPath(jarFiles[i]);
            Path extractedJar = Files.createTempFile("jar-" + i, ".jar");
            Files.copy(nestedJar, extractedJar, StandardCopyOption.REPLACE_EXISTING);
            currentFs.close();
            if (currentJar != null) {
                Files.delete(currentJar);
            }
            currentJar = extractedJar;
            currentFs = FileSystems.newFileSystem(URI.create("jar:file:" + extractedJar),
                    Map.of("create", "true"));
        }
    }
    return currentFs;
}

返回一个文件系统列表,这样您就可以在使用后关闭它们,而不是泄漏FD。

票数 0
EN

Stack Overflow用户

发布于 2022-02-21 06:18:01

这个问题至少在Java 14中得到了解决(也许更早)。OP的代码只需进行一次更改:您需要为ClassLoader的第二个参数newFileSystem添加一个显式强制转换。

对于更完整的示例,此代码打印README.md的内容,该内容位于internal.zip存档中,该存档本身位于archive.zip存档中:

代码语言:javascript
复制
import java.io.IOException;
import java.nio.file.*;

public class Test {
    public static void main(String[] args) throws IOException {
        Path zipfile = Paths.get("archive.zip");
        FileSystem manager = FileSystems.newFileSystem(zipfile, (ClassLoader) null);
        Path internal = manager.getPath("internal.zip");
        FileSystem internalManager = FileSystems.newFileSystem(internal, (ClassLoader) null);
        Path internalFile = internalManager.getPath("README.md");
        Files.lines(internalFile).forEach(System.out::println);
    }
}

注意档案中的文件名是区分大小写的.

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26219534

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档