【问题标题】:File loading by getClass().getResource()通过 getClass().getResource() 加载文件
【发布时间】:2012-12-14 21:04:12
【问题描述】:

我已经按照getClass.getResource(path)的方式加载资源文件了。代码的 sn-p 在这里:

String url = "Test.properties";

System.out.println("Before printing paths..");
System.out.println("Path2: "+ getClass().getResource(url).getPath());

FileInputStream inputStream = new FileInputStream(new File(getClass().getResource(url).toURI()));
i_propConfig.load(inputStream);
inputStream.close();

我已经在 Eclipse 中配置了它的层次结构(在源代码下有一个名为 SwingDemo 的文件夹。在 SwingDemo 中有我的 java 文件以及资源文件)...

    • Swing演示
      1. CustomDialog.java
      2. Test.properties

当我在 Eclipse 上运行它时,一切都运行良好。但是一旦我尝试从命令行运行应用程序,就会发生空指针异常..

命令行部署层次如下:

文件夹:D:\Work\Java Progrms\SwingDemo

层次结构:

  1. Swing演示
    • CustomDialog.java
    • Test.properties

首先,我从命令行 (javac CustomDialog.java) 在 SwingDemo 文件夹中编译了这个文件。然后我回到 Java Programs 文件夹(正如我在 .java 类中提到的包)并使用著名的

运行应用程序
java SwingDemo.CustomDialog

我以前使用 new FileInputStream("path") 时曾经遵循类似的步骤。 这样做后,我得到空指针异常..

我认为getClass().getResource(url) 无法从特定目录加载文件。这就是为什么我将资源与我的 java 文件放在同一目录中的原因。它在 Eclipse 中运行良好。但是为什么当我从命令行运行时会出错。

【问题讨论】:

    标签: java file load embedded-resource


    【解决方案1】:

    从 jar 中的资源文件夹访问文件的最佳方法是通过 getResourceAsStream 使用 InputStream。如果您仍然需要资源作为文件实例,您可以将资源作为流复制到临时文件中(JVM 退出时临时文件将被删除):

    public static File getResourceAsFile(String resourcePath) {
        try {
            InputStream in = ClassLoader.getSystemClassLoader().getResourceAsStream(resourcePath);
            if (in == null) {
                return null;
            }
    
            File tempFile = File.createTempFile(String.valueOf(in.hashCode()), ".tmp");
            tempFile.deleteOnExit();
    
            try (FileOutputStream out = new FileOutputStream(tempFile)) {
                //copy stream
                byte[] buffer = new byte[1024];
                int bytesRead;
                while ((bytesRead = in.read(buffer)) != -1) {
                    out.write(buffer, 0, bytesRead);
                }
            }
            return tempFile;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
    

    【讨论】:

    • 非常有帮助的答案。我希望能够投票更多次:D。我认为它也可以使用这行代码 InputStream in = getClass().getResourceAsStream(resourcePath);
    • 我也面临着类似的问题。我有一个 json 文件,我需要读取该文件并对其进行更新。如何做到这一点?
    • 你不应该关闭in吗?
    • 这应该被标记为接受的答案。这个答案帮助我在 Kotlin 项目中创建 jar 文件时处理文件。
    【解决方案2】:

    getClass().getResource() 使用类加载器来加载资源。这意味着资源必须在要加载的类路径中。

    在使用 Eclipse 时,您放在源文件夹中的所有内容都由 Eclipse “编译”:

    • .java 文件被编译成 .class 文件进入 bin 目录(默认)
    • 其他文件被复制到 bin 目录(尊重包/文件夹层次结构)

    当使用 Eclipse 启动程序时,bin 目录因此位于类路径中,并且由于它包含 Test.properties 文件,因此该文件可以由类加载器加载,使用 getResource()getResourceAsStream()

    如果它不能从命令行运行,那是因为文件不在类路径中。

    请注意,您不应该这样做

    FileInputStream inputStream = new FileInputStream(new File(getClass().getResource(url).toURI()));
    

    加载资源。因为只有从文件系统加载文件才能工作。如果你将你的应用程序打包成一个 jar 文件,或者你通过网络加载类,它就不会工作。要获取 InputStream,只需使用

    getClass().getResourceAsStream("Test.properties")
    

    最后,如文档所示,

    Foo.class.getResourceAsStream("Test.properties")
    

    将加载与类 Foo 位于同一包中的 Test.properties 文件。

    Foo.class.getResourceAsStream("/com/foo/bar/Test.properties")
    

    将加载位于包com.foo.bar 中的Test.properties 文件。

    【讨论】:

    • 这对我有帮助:“如果您将应用程序打包到 jar 文件中,或者如果您通过网络加载类,它将无法工作。” --> 你需要从文件中获取一个 InputStream。
    猜你喜欢
    • 1970-01-01
    • 2020-06-13
    • 2013-11-30
    • 1970-01-01
    • 2013-01-13
    相关资源
    最近更新 更多