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 构建时使用默认设置,但我对这个问题失去了理智。
任何提示或想法将不胜感激!
这里有两个问题。
Windows 是 case-insensitive。其他平台和jar里面的名字是case-sensitive.
getClass()
class 决定了在哪个 jar/class 路径中寻找资源。特别是单元测试不会放在罐子里,或者 child class 可能位于罐子外面。使用 SomeClassInJar.class
或使用搜索所有 jars/class 路径的 ClassLoader。 class 加载程序仅使用绝对路径,您不得以 /
.
开头路径
我认为 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 代码中发出一些权限错误信号。
衷心感谢所有相关人员的帮助!
我知道同一个问题已经被问过很多次了,但是浏览了所有已经发布的答案我找不到解决方案。
首先,这是我在项目中遇到问题后用来测试问题的代码:
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 构建时使用默认设置,但我对这个问题失去了理智。
任何提示或想法将不胜感激!
这里有两个问题。
Windows 是 case-insensitive。其他平台和jar里面的名字是case-sensitive.
getClass()
class 决定了在哪个 jar/class 路径中寻找资源。特别是单元测试不会放在罐子里,或者 child class 可能位于罐子外面。使用SomeClassInJar.class
或使用搜索所有 jars/class 路径的 ClassLoader。 class 加载程序仅使用绝对路径,您不得以/
. 开头路径
我认为 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 代码中发出一些权限错误信号。
衷心感谢所有相关人员的帮助!