getResourceAsStream() returns 仅在 jar 文件中时为 null

getResourceAsStream() returns null only when in jar file

我知道同一个问题已经被问过很多次了,但是浏览了所有已经发布的答案我找不到解决方案。

首先,这是我在项目中遇到问题后用来测试问题的代码:

InputStream test;

System.out.println(this.getClass());
System.out.println(("classpath is: " + System.getProperty("java.class.path")));

test = getClass().getResourceAsStream("/pairs/images/100/back/back1.png");

if (test == null)
{
    System.out.println("getClass().getResourceAsStream(\"/pairs/images/100/back/back1.png\") is null");
    test = GridPanel.class.getClassLoader().getResourceAsStream("pairs/images/100/back/back1.png");
}

if (test == null)
{
    System.out.println("GridPanel.class.getClassLoader().getResourceAsStream(\"pairs/images/100/back/back1.png\") is null");
    test = ClassLoader.getSystemClassLoader().getResourceAsStream("pairs/images/100/back/back1.png");
}

if (test == null)
{
    System.out.println("ClassLoader.getSystemClassLoader().getResourceAsStream(\"pairs/images/100/back/back1.png\") is null");
    Thread.currentThread().getContextClassLoader().getResourceAsStream("pairs/images/100/back/back1.png");
}

if (test == null)
    System.out.println("Thread.currentThread().getContextClassLoader().getResourceAsStream(\"pairs/images/100/back/back1.png\") is null");

因此,根据标题,每个对 getResourceAsStream() return 的调用都是空的,但只有在执行 jar 文件时,在 IDE (Netbeans 8.0.2) 中启动时,它们都是return 正确的流(没有使用这段代码单独测试),我可以使用它。

jar文件内容如下:

而netbeans项目文件夹中的src文件夹如下:

所以我现在真的很困惑,我试过在使用 netbeans 构建时使用默认设置,但我对这个问题失去了理智。

任何提示或想法将不胜感激!

这里有两个问题。

  1. Windows 是 case-insensitive。其他平台和jar里面的名字是case-sensitive.

  2. getClass() class 决定了在哪个 jar/class 路径中寻找资源。特别是单元测试不会放在罐子里,或者 child class 可能位于罐子外面。使用 SomeClassInJar.class 或使用搜索所有 jars/class 路径的 ClassLoader。 class 加载程序仅使用绝对路径,您不得以 /.

  3. 开头路径

我认为 getResourceAsStream 不是从文件系统读取,前导斜杠将尝试从 class 路径的根读取(如果添加目录将从根读取)。如果您不放置前导斜杠,您将从 class 所在的包中读取。

您是否在 class 路径中添加了要从中读取文件的 directory/subdirectories?

TL;DR 这是由于 NTFS 权限的一些愚蠢问题,移动 jar 使其工作

所以我现在觉得很傻...

我在 Linux 环境中尝试 运行 它,一切正常。 这些调用中的每一个都是 return 指向资源的非空 InputStream。

所以我做了一些非常简单的事情:只是在 Windows 中移动编译的 jar 来检查它是否与 NTFS 权限有关(请记住,我使用的是管理员帐户,我可以在这些文件夹中自由写入、读取和执行)。 将它移动到项目的根目录不起作用,但将它移动到桌面上工作。

更让我惊讶的是,在我正在做的项目的其他一些部分

URL jarUrl = PairsDeck.class.getProtectionDomain().getCodeSource().getLocation();

读取 jar 文件的全部内容,即使在旧目录中,每次也能正常工作,所以这就是为什么我从一开始就没有考虑过权限问题(我是从命令提示符启动它的管理员权限)。

所以我猜想程序可以通过该调用读取它的 jar,但由于 NTFS 权限的一些问题而无法从它加载资源到我的 netbeans 项目文件夹中。

增加一些混乱

File file = new File(jarUrl.toURI());
file.canWrite();
file.canRead();
file.canExecute(); 

以上都是return正确。

我只是想知道是否有办法更好地理解这个问题,也许有办法从 java 代码中发出一些权限错误信号。

衷心感谢所有相关人员的帮助!