java.nio.file.FileSystemNotFoundException 从资源文件夹获取文件时
java.nio.file.FileSystemNotFoundException when getting file from resources folder
我在以下代码中遇到此错误(请注意,这不会发生在我的本地计算机上,只会发生在我的构建服务器上):
Files.readAllBytes(Paths.get(getClass().getResource("/elasticsearch/segmentsIndex.json").toURI()), Charset.defaultCharset());
例外情况:
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)
我尝试按照此 solution 修复它;我的代码现在看起来像这样:
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);
我收到以下异常:
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)
似乎没有任何效果。
我应该如何构建文件的路径?
一般来说,假设每个资源都是一个文件是不正确的。相反,您应该获取该资源的 URL/InputStream 并从那里读取字节。 Guava 可以提供帮助:
URL url = getClass().getResource("/elasticsearch/segmentsIndex.json");
String content = Resources.toString(url, charset);
另一种可能的解决方案,使用 InputStream 和 apache commons:Convert InputStream to byte array in Java .
从一个 byte[],只需使用 String 构造函数获取字符串形式的内容。
不要尝试访问文件等资源。只需获取 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
}
此示例使用来自 Apache commons-io 库的 IOUtils class。
如果您的目标是 Java 9+,您也可以使用 data = in.readAllBytes();
。
您应该使用 getResourceAsStream(…)
而不是 getResource(…)
。有许多方法可以将所有字节读入字节数组,例如Apache Commons 有一个实用方法可以做到这一点。
您应该通过 InputStream
而不是 File
获取资源,但不需要外部库。
您只需要几行代码:
InputStream is = getClass().getResourceAsStream("/elasticsearch/segmentsIndex.json");
java.util.Scanner scanner = new java.util.Scanner(is).useDelimiter("\A");
String json = scanner.hasNext() ? scanner.next() : "";
您可以在
了解有关该方法的更多信息
如果使用Spring,注入资源。无论是一个文件,还是文件夹,甚至是多个文件,都有机会,你可以通过注入来完成。警告:不要将 File
和 Files.walk
与注入的资源一起使用,否则当 运行 作为 JAR 时你会得到 FileSystemNotFoundException
。
此示例演示了如何注入位于 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 WhosebugService {
@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());
}
}
我在以下代码中遇到此错误(请注意,这不会发生在我的本地计算机上,只会发生在我的构建服务器上):
Files.readAllBytes(Paths.get(getClass().getResource("/elasticsearch/segmentsIndex.json").toURI()), Charset.defaultCharset());
例外情况:
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)
我尝试按照此 solution 修复它;我的代码现在看起来像这样:
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);
我收到以下异常:
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)
似乎没有任何效果。 我应该如何构建文件的路径?
一般来说,假设每个资源都是一个文件是不正确的。相反,您应该获取该资源的 URL/InputStream 并从那里读取字节。 Guava 可以提供帮助:
URL url = getClass().getResource("/elasticsearch/segmentsIndex.json");
String content = Resources.toString(url, charset);
另一种可能的解决方案,使用 InputStream 和 apache commons:Convert InputStream to byte array in Java .
从一个 byte[],只需使用 String 构造函数获取字符串形式的内容。
不要尝试访问文件等资源。只需获取 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
}
此示例使用来自 Apache commons-io 库的 IOUtils class。
如果您的目标是 Java 9+,您也可以使用 data = in.readAllBytes();
。
您应该使用 getResourceAsStream(…)
而不是 getResource(…)
。有许多方法可以将所有字节读入字节数组,例如Apache Commons 有一个实用方法可以做到这一点。
您应该通过 InputStream
而不是 File
获取资源,但不需要外部库。
您只需要几行代码:
InputStream is = getClass().getResourceAsStream("/elasticsearch/segmentsIndex.json");
java.util.Scanner scanner = new java.util.Scanner(is).useDelimiter("\A");
String json = scanner.hasNext() ? scanner.next() : "";
您可以在
了解有关该方法的更多信息如果使用Spring,注入资源。无论是一个文件,还是文件夹,甚至是多个文件,都有机会,你可以通过注入来完成。警告:不要将 File
和 Files.walk
与注入的资源一起使用,否则当 运行 作为 JAR 时你会得到 FileSystemNotFoundException
。
此示例演示了如何注入位于 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 WhosebugService {
@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());
}
}