当前位置: 首页 > 知识库问答 >
问题:

无法访问JavaFX 16中存在module-info.java资源文件

魏泰
2023-03-14

我刚开始使用Java16,似乎不明白为什么我不能访问资源文件。我进行了一些故障排除,以缩小范围,至少在我似乎有问题的地方。

我正在使用IntelliJ IDEA 2021.2构建#IU-212.4746.92

我创建了一个新项目,我选择了带有OpenJDK 16的JavaFX。

然后,它用三个主文件创建项目,一个应用程序类、一个控制器类和一个FXML文件。创建项目后,我进入POM文件,选择了JavaFXControls和JavaFXFXML的版本16,并告诉它获取自动添加到POM文件中的其他库的最新版本。

我还将两个文件夹从不同的项目复制到资源文件夹中-所有的复制和粘贴都是在IntelliJ中完成的。

当我运行它放在那里的应用程序(称为HellpApplication)时,它工作正常。该应用程序使用类。getResource获取fxml文件,然后重试。。。它很好用。但是,当我尝试运行此类时:

import java.io.*;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.List;

public class FileResourcesUtils {

    public static void main(String[] args) throws URISyntaxException {
        FileResourcesUtils app = new FileResourcesUtils();
        String fileName = "StyleSheets/AnchorPane.css";
        System.out.println("getResourceAsStream : " + fileName);
        InputStream is = app.getFileFromResourceAsStream(fileName);
        printInputStream(is);
        System.out.println("\ngetResource : " + fileName);
        File file = app.getFileFromResource(fileName);
        printFile(file);
    }

    private InputStream getFileFromResourceAsStream(String fileName) {
        ClassLoader classLoader = getClass().getClassLoader();
        InputStream inputStream = classLoader.getResourceAsStream(fileName);
        if (inputStream == null) {
            throw new IllegalArgumentException("file not found! " + fileName);
        }
        else return inputStream;
    }

    private File getFileFromResource(String fileName) throws URISyntaxException{

        ClassLoader classLoader = getClass().getClassLoader();
        URL resource = classLoader.getResource(fileName);
        if (resource == null) {
            throw new IllegalArgumentException("file not found! " + fileName);
        }
        else return new File(resource.toURI());}

    private static void printInputStream(InputStream is) {
        try (InputStreamReader streamReader =
                     new InputStreamReader(is, StandardCharsets.UTF_8);
                     BufferedReader reader = new BufferedReader(streamReader)
        ) 
        {
            String line;
            while ((line = reader.readLine()) != null) System.out.println(line);
        } 
        catch (IOException e) {e.printStackTrace();}
    }

    private static void printFile(File file) {
        List<String> lines;
        try {
            lines = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8);
            lines.forEach(System.out::println);
        }
        catch (IOException e) {e.printStackTrace();}
    }

}

它抛出以下错误:

getResourceAsStream : StyleSheets/AnchorPane.css
Exception in thread "main" java.lang.IllegalArgumentException: file not found! StyleSheets/AnchorPane.css
    at com.simtechdata.test/com.simtechdata.test.FileResourcesUtils.getFileFromResourceAsStream(FileResourcesUtils.java:27)
    at com.simtechdata.test/com.simtechdata.test.FileResourcesUtils.main(FileResourcesUtils.java:16)

然后,我唯一要做的就是删除module-info.java,然后类运行完美!然而,没有module-info.java,我不能运行任何外汇代码...

这是模块信息。爪哇:

module com.simtechdata.test {
    requires javafx.controls;
    requires javafx.fxml;


    opens com.simtechdata.test to javafx.fxml;
    exports com.simtechdata.test;
}

我为什么要上这门课?因为我在尝试访问JavaFX应用程序中的资源文件时遇到了完全相同的问题,这个类是我演示这个问题并显示它专门连接到模块信息文件的最简单方法。当我运行自己的JavaFX代码时,它工作得很好,直到我尝试访问一个资源文件(比如样式表)以添加到控件上。

我想知道的是。。。为了能够从JavaFX16应用程序访问资源文件,我需要做什么样的魔术?我错过了什么?

我尝试了所有这些不同的方法来获取资源文件,但是每个方法都给出了相同的错误:

String CSS_ANCHOR_PANE = this.getClass().getResource("StyleSheets/AnchorPane.css").toExternalForm();
String CSS_ANCHOR_PANE = ClassName.getClass().getResource("StyleSheets/AnchorPane.css").toExternalForm();

ClassLoader resource = ClassLoader.getSystemClassLoader();
String CSS_ANCHOR_PANE = resource.getResource("StyleSheets/AnchorPane.css").toExternalForm();

Class<?> resource = this.getClass();
String CSS_ANCHOR_PANE = resource.getResource("StyleSheets/AnchorPane.css").toExternalForm();

下面是资源文件夹树的屏幕截图:

有什么想法吗?

共有2个答案

魏学智
2023-03-14

>

您可以通过不使用模块系统来解决此问题。只需将您的主要方法包装成如下内容:

类MyAppLauncher{公共静态无效主(字符串[]参数){MyApp.main(参数);}}

假设MyApp是扩展Application的主类。使用MyAppLauncher启动JavaFX程序并删除所有模块系统相关选项。

梁丘成和
2023-03-14

这个问题在StackOverflow站点周围的许多其他地方得到了真正的回答,但是我将在这里汇集各种解决方案。

你基本上有三个选择:

  1. 使用在Class中定义的getResources()(或getResourceAsStream(),尽管前者更可取)方法,而不是在ClassLoader中使用正确的路径。这避免了模块化的任何问题。
  2. 使项目非模块化(即不定义module-info.java文件),并指定要作为运行时参数添加到JVM的模块。这允许您使用ClassLoadergetResources()ClassgetResources()方法。
  3. 创建一个模块化项目,使用ClassLoadergetResouce()方法,无条件打开包含资源的包。

这里详细介绍了解决方案1。由于您正在加载的样式表位于样式表1中,并且您从中加载样式表的类(从堆栈跟踪)显示为位于不相关的包com中。simtechdata。测试时,应提供绝对路径:

String CSS_ANCHOR_PANE = this.getClass().getResource("/StyleSheets/AnchorPane.css").toExternalForm();

对于解决方案2,使用

String CSS_ANCHOR_PANE = this.getClass().getClassLoader().getResource("StyleSheets/AnchorPane.css").toExternalForm();

删除module-info.java文件,并使用JVM参数运行应用程序

--module-path="/path/to/javafx/modules" --add-modules="javafx.controls,javafx.fxml"

(将/path/to/javafx/modules替换为指向javafx模块的实际文件系统路径。javafx.fxml模块仅在使用fxml的add modules参数中是必需的。)

对于解决方案3,使用

String CSS_ANCHOR_PANE = this.getClass().getClassLoader().getResource("StyleSheets/AnchorPane.css").toExternalForm();

由于您的资源位于StyleSheets1中,因此您需要无条件地打开该包。添加行

opens StyleSheets ;

到您的模块信息。java文件。看见https://stackoverflow.com/a/48790851/2189127

(1) 强烈建议遵循标准命名约定;我甚至不确定解决方案3是否可以使用非标准的包名(包名应该都是小写)。

 类似资料:
  • 问题内容: 我的/ res / raw /文件夹(/res/raw/textfile.txt)中有一个资源文件,我正在尝试从我的android应用中读取该文件进行处理。 我尝试了不同的路径语法,但始终会遇到 java.io.FileNotFoundException 错误。如何访问/res/raw/textfile.txt进行处理?是 File file = new File(“ res / ra

  • 我正在尝试实现动态交付类型的APP。首先,我在create模块之后创建新项目,用于此动态步骤 我的crate类和想要访问资源文件夹的使用布局,可绘制文件夹。 在主模块级实现 实现'com.google.android.play:core:1.2.0'和dynamicFeatures=[“:Dynamic_Feature”] 错误:找不到符号变量activity_main 错误:找不到符号变量iv_

  • ServletContext接口定义了三个方法来访问当前Web应用程序的资源文件,这三个方法如下: l getResourcePaths方法 该方法返回指定Web应用程序目录中的所有子目录和文件,这些返回的目录文件不包括嵌套目录和文件。这些返回的子目录和文件都封装在该方法返回的一个Set对象中。getResourcePaths方法的定义如下: public Set getResourcePaths

  • 我正在学习JavaFx并尝试制作一个可重用的组件。该项目正在VSCode中开发。该项目非常简单,涉及启动器和可重用组件。我正在重构,当添加模块时,一切都停止了工作,我无法继续重构。 module-info中显示的错误是:< code>javafx.controls无法解析为模块。虽然很奇怪,但是如果我告诉Maven更新项目,在一些罕见的情况下,错误会告诉我模块是空的或者不存在。 源代码(实验分支)

  • 但我进的是空异常。有什么问题,有人能帮忙吗?

  • 我正在从主类访问资源文件夹中的文件 我收到了这个错误: 我甚至打开了jar文件,remoteUnitsIdsInOldServer.txt文件就在那里,在类内部