java 从资源文件夹中获取文件时出现java.nio.file.FileSystemNotFoundException

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29746667/
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-11-02 15:50:50  来源:igfitidea点击:

java.nio.file.FileSystemNotFoundException when getting file from resources folder

javanio

提问by Gleeb

I am getting this error on the following code (note that this does not happen on my local machine, only on my build server):

我在以下代码中收到此错误(请注意,这不会发生在我的本地机器上,只会发生在我的构建服务器上):

Files.readAllBytes(Paths.get(getClass().getResource("/elasticsearch/segmentsIndex.json").toURI()), Charset.defaultCharset());

And the exception:

和例外:

Caused by: java.nio.file.FileSystemNotFoundException: null
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(Paths.java:143)

I tried to fix it by following this solution; my code now looks like this:

我尝试按照此解决方案修复它;我的代码现在看起来像这样:

URI segmentsIndexURI = getClass().getResource("/elasticsearch/segmentsIndex.json").toURI();
Map<String, String> env = new HashMap<>(); 
env.put("create", "true");
FileSystem zipfs = FileSystems.newFileSystem(segmentsIndexURI, env); //exception here
Path segmentsIndexPath = Paths.get(segmentsIndexURI);

I am getting the following exception:

我收到以下异常:

java.lang.IllegalArgumentException: Path component should be '/'
at sun.nio.fs.UnixFileSystemProvider.checkUri(UnixFileSystemProvider.java:77)
at sun.nio.fs.UnixFileSystemProvider.newFileSystem(UnixFileSystemProvider.java:86)
at java.nio.file.FileSystems.newFileSystem(FileSystems.java:326)
at java.nio.file.FileSystems.newFileSystem(FileSystems.java:276)

Nothing seems to work. How am I supposed to build the path to the file?

似乎没有任何效果。我应该如何构建文件的路径?

回答by Robert

Don't try to access a resource like a file. Just grab the InputStream and read the data from there:

不要尝试访问像文件这样的资源。只需获取 InputStream 并从那里读取数据:

byte[] data;
try (InputStream in = getClass().getResourceAsStream("/elasticsearch/segmentsIndex.json")) {
    data = in.readAllBytes?(); // usable in Java 9+
    // data = IOUtils.toByteArray(in); // uses Apache commons IO library
}

This example uses the IOUtils class from Apache commons-io library.

此示例使用 Apache commons-io 库中的 IOUtils 类。

If you are targeting Java 9+ you can alternatively use data = in.readAllBytes?();.

如果您的目标是 Java 9+,您也可以使用data = in.readAllBytes?();.

回答by botismarius

Generally, it is not correct to assume that every resource is a file. Instead, you should obtain the URL/InputStream for that resource and read the bytes from there. Guava can help:

通常,假设每个资源都是一个文件是不正确的。相反,您应该获取该资源的 URL/InputStream 并从那里读取字节。番石榴可以帮助:

URL url = getClass().getResource("/elasticsearch/segmentsIndex.json");
String content = Resources.toString(url, charset);


Another possible solution, with the InputStream and apache commons: Convert InputStream to byte array in Java.


另一个可能的解决方案,具有 InputStream 和 apache 的共同点:在 Java中将 InputStream转换为字节数组

From a byte[], simply use the String constructor to obtain the content as a string.

从 byte[] 中,只需使用 String 构造函数即可获取字符串形式的内容。

回答by isapir

You should get the resource through an InputStreamand not a File, but there is no need for external libraries.

您应该通过 anInputStream而不是 a获取资源File,但不需要外部库。

All you need is a couple of lines of code:

您只需要几行代码:

InputStream is = getClass().getResourceAsStream("/elasticsearch/segmentsIndex.json");
java.util.Scanner scanner = new java.util.Scanner(is).useDelimiter("\A");
String json = scanner.hasNext() ? scanner.next() : "";

You can learn more about that method at https://stackoverflow.com/a/5445161/968244

您可以在https://stackoverflow.com/a/5445161/968244 上了解有关该方法的更多信息

回答by naXa

If you use Spring, inject resources. Be it a file, or folder, or even multiple files, there are chances, you can do it via injection. Warning: DO NOT use Fileand Files.walkwith the injected resources, otherwise you'll get FileSystemNotFoundExceptionwhen running as JAR.

如果使用 Spring,请注入资源。无论是文件,文件夹,甚至是多个文件,都有机会,您可以通过注入来完成。警告:不要使用FileFiles.walk注入的资源,否则你会FileSystemNotFoundException在作为 JAR 运行时得到。

This example demonstrates the injection of multiple images located in static/imgfolder.

此示例演示了注入位于static/img文件夹中的多个图像。

import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;

@Service
public class StackoverflowService {

    @Value("classpath:static/img/*")
    private Resource[] resources;
    private List<String> filenames;

    @PostConstruct
    void init() {
        final Predicate<String> isJPG = path -> path.endsWith(".jpg");
        final Predicate<String> isPNG = path -> path.endsWith(".png");

        // iterate resources, filter by type and get filenames
        filenames = Arrays.stream(resources)
                .map(Resource::getFilename)
                .filter(isJPG.or(isPNG))
                .collect(Collectors.toList());
    }
}

回答by llogiq

You should be using getResourceAsStream(…)instead of getResource(…). There are a number of methods to read all bytes into a byte array, e.g. Apache Commons has a utility method to do just that.

您应该使用getResourceAsStream(…)而不是getResource(…). 有多种方法可以将所有字节读入字节数组,例如 Apache Commons 有一个实用方法可以做到这一点。