jar 中的 Java 访问文件导致 java.nio.file.FileSystemNotFoundException

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22605666/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 16:48:09  来源:igfitidea点击:

Java access files in jar causes java.nio.file.FileSystemNotFoundException

javajava-7nio

提问by tom91136

While trying to copy some files in my jar file to a temp directory with my java app, the following exception is thrown:

尝试使用我的 java 应用程序将 jar 文件中的某些文件复制到临时目录时,抛出以下异常:

java.nio.file.FileSystemNotFoundException
    at com.sun.nio.zipfs.ZipFileSystemProvider.getFileSystem(ZipFileSystemProvider.java:171)
    at com.sun.nio.zipfs.ZipFileSystemProvider.getPath(ZipFileSystemProvider.java:157)
    at java.nio.file.Paths.get(Unknown Source)
    at com.sora.util.walltoggle.pro.WebViewPresentation.setupTempFiles(WebViewPresentation.java:83)
   ....

and this is a small part of my setupTempFiles(with line numbers):

这是我的一小部分setupTempFiles(带有行号):

81. URI uri = getClass().getResource("/webViewPresentation").toURI();
//prints: URI->jar:file:/C:/Users/Tom/Dropbox/WallTogglePro.jar!/webViewPresentation
82. System.out.println("URI->" + uri );
83. Path source = Paths.get(uri);

the webViewPresentationdirectory resides in the root directory of my jar:

webViewPresentation目录位于我的 jar 的根目录中:

enter image description here

在此处输入图片说明

This problem only exits when I package my app as a jar, debugging in Eclipse has no problems. I suspect that this has something to do with this bugbut I'm not sure how to correct this problem.

只有当我将我的应用程序打包为 jar 时才会出现此问题,在 Eclipse 中调试没有问题。我怀疑这与此错误有关,但我不确定如何更正此问题。

Any helps appreciated

任何帮助表示赞赏

If matters:

如果重要:

I'm on Java 8 build 1.8.0-b132

我在 Java 8 build 1.8.0-b132

Windows 7 Ult. x64

Windows 7 终极版 x64

采纳答案by fge

A FileSystemNotFoundExceptionmeans the file system cannot be created automatically; and you have not created it here.

AFileSystemNotFoundException表示无法自动创建文件系统;你还没有在这里创建它。

Given your URI, what you should do is split against the !, open the filesystem using the part before it and then get the path from the part after the !:

给定您的 URI,您应该做的是拆分!,使用它之前的部分打开文件系统,然后从 之后的部分获取路径!

final Map<String, String> env = new HashMap<>();
final String[] array = uri.toString().split("!");
final FileSystem fs = FileSystems.newFileSystem(URI.create(array[0]), env);
final Path path = fs.getPath(array[1]);

Note that you should .close()your FileSystemonce you're done with it.

请注意,您应该.close()FileSystem一旦你用它做。

回答by hemanto

If you're using spring framework library, then there is an easy solution for it.

如果您使用的是 spring 框架库,那么有一个简单的解决方案。

As per requirement we want to read webViewPresentation; I could solve the same problem with below code:

根据要求,我们要阅读 webViewPresentation;我可以用下面的代码解决同样的问题:

URI uri = getClass().getResource("/webViewPresentation").toURI();
FileSystems.getDefault().getPath(new UrlResource(uri).toString());

回答by Kinmarui

Accepted answer isn't the best since it doesn't work when you start application in IDE or resource is static and stored in classes! Better solution was proposed at java.nio.file.FileSystemNotFoundException when getting file from resources folder

接受的答案不是最好的,因为当您在 IDE 中启动应用程序或资源是静态的并存储在类中时它不起作用!从资源文件夹中获取文件时,java.nio.file.FileSystemNotFoundException中提出了更好的解决方案

InputStream in = getClass().getResourceAsStream("/webViewPresentation");
byte[] data = IOUtils.toByteArray(in);

IOUtils is from Apache commons-io.

IOUtils 来自 Apache commons-io。

But if you are already using Spring and want a text file you can change the second line to

但是如果你已经在使用 Spring 并且想要一个文本文件,你可以将第二行更改为

StreamUtils.copyToString(in, Charset.defaultCharset());

StreamUtils.copyToByteArray also exists.

StreamUtils.copyToByteArray 也存在。

回答by fuemf5

This is maybe a hack, but the following worked for me:

这可能是一个黑客,但以下对我有用:

URI uri = getClass().getResource("myresourcefile.txt").toURI();

if("jar".equals(uri.getScheme())){
    for (FileSystemProvider provider: FileSystemProvider.installedProviders()) {
        if (provider.getScheme().equalsIgnoreCase("jar")) {
            try {
                provider.getFileSystem(uri);
            } catch (FileSystemNotFoundException e) {
                // in this case we need to initialize it first:
                provider.newFileSystem(uri, Collections.emptyMap());
            }
        }
    }
}
Path source = Paths.get(uri);

This uses the fact that ZipFileSystemProvider internally stores a List of FileSystems that were opened by URI.

这使用了 ZipFileSystemProvider 在内部存储由 URI 打开的文件系统列表的事实。