运行 JAR(Fxyz3d 库)时出现 FileSystemNotFoundException

ano*_*aco 5 java javafx jar fxyz3d

我构建了一个非常胖的 JavaFX 应用程序(JAR 大约 128 MB)并且通过 IntelliJ 运行没有问题。但是当我从终端运行它时,我的 3D 模型加载器(Fxyz3d 库)启动了这个异常。

Exception in thread "JavaFX Application Thread" java.nio.file.FileSystemNotFoundException
    at jdk.zipfs/jdk.nio.zipfs.ZipFileSystemProvider.getFileSystem(ZipFileSystemProvider.java:172)
    at jdk.zipfs/jdk.nio.zipfs.ZipFileSystemProvider.getPath(ZipFileSystemProvider.java:158)
    at java.base/java.nio.file.Path.of(Path.java:208)
    at java.base/java.nio.file.Paths.get(Paths.java:98)
    at org.fxyz3d.importers.obj.ObjImporter.read(ObjImporter.java:115)
    at org.fxyz3d.importers.obj.ObjImporter.loadAsPoly(ObjImporter.java:102)
    at org.fxyz3d.importers.Importer3D.loadIncludingAnimation(Importer3D.java:160)
    at org.fxyz3d.importers.Importer3D.loadAsPoly(Importer3D.java:80)
    at it.polimi.ingsw.PSP50.View.GUI.GuiView.lambda$startingGame$1(GuiView.java:201)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96) 
Run Code Online (Sandbox Code Playgroud)

这仅针对 Fxyz3d 库中的 3D 对象加载器抛出,而不针对我的其他普通 FXML 加载器。我使用相同的方式从我的 src/main/resources 文件夹中获取文件,即 getClass().getResource。那么这真的是路径问题吗?还是图书馆的问题?在 IntelliJ 中完全没有问题,一切正常。这是代码中不起作用的部分:

Model3D boardModel = Importer3D.loadAsPoly(getClass().getResource("/boardcliff2.obj"));
 
Run Code Online (Sandbox Code Playgroud)

如果有人以前遇到过这样的事情并且知道发生了什么,那么将非常感谢您的帮助

Sla*_*law 4

Jos\xc3\xa9 Pereda为此提出了一个问题,现已修复。截至目前(2020 年 8 月 14 日),FXyz 的最新版本是 0.5.2,其中不包含此问题的修复。您可以继续使用此答案中显示的解决方法,从最近的提交自行构建库,或者等待库的下一个版本。

\n
\n

这似乎是实施方面的问题。它尝试将 转换URL为 aPath但所需的1FileSystem不存在。最好的解决方法可能是将资源提取到临时文件中,然后从该文件导入对象。这样 URL 将有一个协议并且转换将起作用(默认file:PathFileSystem始终存在)。以下是如何提取资源的示例:

\n
// Note: \'Path\' is \'java.nio.file.Path\', not \'javafx.scene.shape.Path\'\npublic static Path copyToTempFile(URL url, String suffix) throws IOException {\n  // \'suffix\' will default to ".tmp" if null\n  Path tempFile = Files.createTempFile(null, suffix);\n  try (InputStream in = url.openStream();\n       OutputStream out = Files.newOutputStream(tempFile)) {\n    in.transferTo(out); // \'transferTo\' method added in Java 9\n  }\n  return tempFile;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

然后您可以使用生成的结果Path导入 3D 对象:

\n
Path tempFile = copyToTempFile(getClass().getResource("/boardcliff2.obj"), ".obj");\nModel3D boardModel = Importer3D.loadAsPoly(tempFile.toUri().toURL());\n
Run Code Online (Sandbox Code Playgroud)\n

如果需要,您可以在使用完临时文件后将其删除。

\n
\n

1. 当嵌入到 JAR 文件中时,资源的 URL 具有协议jar:。这意味着FileSystemZIP FileSystemProvider打开到特定 ZIP/JAR 文件的文件必须存在才能进行转换Path。如果仅使用实现URL#openStream(),即通过不同的机制访问 JAR 条目,则不会出现此问题。

\n