【问题标题】:class.getResource unconsistant behavior in-Eclipse vs in-jarEclipse 与 jar 中的 class.getResource 行为不一致
【发布时间】:2014-07-20 11:54:47
【问题描述】:

我正在测试如何表达资源文件的路径。我在 Eclipse 和带有 jar 的命令行之间得到了不同的结果。

您能帮我理解为什么会有差异吗?

我有两个资源文件:

  • 一个在类包中,与类文件处于同一级别。
  • 一个在类包外,与包同级。

日食。这确实有效:

package com.example.mypackage;

/*    FileIO (project)
 *      |
 *      +---- src (source folder)
 *             |
 *             +---- com.example.mypackage (package)
 *             |              |
 *             |              +---- TestRes.java (class)
 *             |              |
 *             |              +---- users (resource file 1)
 *             |
 *             +---- test.txt (resource file 2)
 */

public class TestRes {
    public static void main(String[] args) {
        // Some resource names (relative, absolute)
        String[][] res = {
            { "users"            , "/com/example/mypackage/users" },
            { "../../../test.txt", "/test.txt" },
            { "."                , "/com/example/mypackage/" }
        };

        // Get resource URL
        String f = "Relative: %s\nAbsolute: %s\nURL: %s (%s)\n\n";
        for (String[] r : res) {
            String n0 = r[0];
            String n1 = r[1];
            try {
                String url0 = TestRes.class.getResource(n0).getPath();
                String url1 = TestRes.class.getResource(n1).getPath();
                System.out.printf(f, n0, n1, url0, (url0.equals(url1)));
            }
            catch (Exception e) { e.printStackTrace(); }
        }
    }
}

输出:

Relative: users
Absolute: /com/example/mypackage/users
URL: /C:/Users/User/workspace/FileIO/bin/com/example/mypackage/users (true)

Relative: ../../../test.txt
Absolute: /test.txt
URL: /C:/Users/User/workspace/FileIO/bin/test.txt (true)

Relative: .
Absolute: /com/example/mypackage/
URL: /C:/Users/User/workspace/FileIO/bin/com/example/mypackage/ (true)

但是当我将项目导出到 jar 时(右键单击 FileIO,然后单击 export),并在命令行中使用 java.exe 运行 jar,然后在尝试处理时 class.getResource() 返回 null第二种情况("../../../test.txt")和第三种情况(".")。

C:\Users\User\Desktop>java -jar TestRes.jar
Relative: users
Absolute: /com/example/mypackage/users
URL: file:/C:/Users/User/Desktop/TestRes.jar!/com/example/mypackage/users (true)

java.lang.NullPointerException
        at com.example.mypackage.TestRes.main(TestRes.java:31)
java.lang.NullPointerException
        at com.example.mypackage.TestRes.main(TestRes.java:31)

我检查了jar的结构:

  • test.txt 位于 jar 的根目录
  • 根目录下还有 3 个附加文件(类路径、项目和清单)
  • TestRes.class 和用户在com\example\mypackage 文件夹中

【问题讨论】:

    标签: java eclipse jar resources


    【解决方案1】:

    从 Eclipse 运行时,IDE 通过映射到 src 和 bin 文件夹上的基本文件系统操作来模拟运行时类加载器行为。在所有极端情况下,模拟行为可能与真实运行时行为不完全匹配。在这种特殊情况下,模拟器似乎没有阻止使用运行时不支持的路径。

    【讨论】:

    • 确实,没有考虑过。深入研究文档,我看到类加载器委托给父类加载器(如果有的话),或者调用 getBootstrapResource 。如果这一步找不到资源,则类加载器调用 findResource 方法,默认不返回任何结果(必须由派生类实现)。由于 getBootstrapResource 不是开源的,我不知道资源可能存储在哪里。你有资源位置限制的链接吗?谢谢。
    • @mins: com/example/mypackage/users 是一个类路径资源。这不是名为mypackage 的目录中名为users 的文件。因此,不要尝试将其作为文件系统中的文件读取。正如您从实验中看到的那样,它并不总是有效,特别是当您知道要创建一个存档文件时,例如 jar、war、...
    • Class.getResource() 的 javadoc 列出了仅支持的两种类型的路径...从包树的根目录或从当前包。没有为父导航或您正在尝试的其他东西提供任何规定。这些不是文件系统路径。 docs.oracle.com/javase/8/docs/api/java/lang/…
    • @KonstantinKomissarchik:谢谢。我明白了。
    • @Bhesh Gurung:谢谢。我不确定我是否完全理解你的意思。我的理解是资源名称的结构可以映射到文件系统中的文件夹和文件,或者通过扩展映射到jar中,至少在Windows下是这样。如果这在我以外的情况下无效,请纠正我。我已经在 Eclipse 和 jar 中使用“TestRes.class.getResourceAsStream(r[1])”阅读了“用户”内容。
    猜你喜欢
    • 2012-10-27
    • 1970-01-01
    • 2015-03-29
    • 2012-08-23
    • 2013-09-07
    • 2010-12-23
    • 2013-09-02
    • 2020-02-28
    • 2022-01-24
    相关资源
    最近更新 更多