为啥 getResourceAsStream() 可以在 IDE 中工作,但不能在 JAR 中工作?

Posted

技术标签:

【中文标题】为啥 getResourceAsStream() 可以在 IDE 中工作,但不能在 JAR 中工作?【英文标题】:Why does getResourceAsStream() work in the IDE but not the JAR?为什么 getResourceAsStream() 可以在 IDE 中工作,但不能在 JAR 中工作? 【发布时间】:2013-04-09 11:46:34 【问题描述】:

我只想将一个文件读入我的程序。该文件位于“../f.fsh”工作目录上方的一个目录。所以当我在 IDE 中运行以下代码时,它可以正确运行

String name="../f.fsh";
InputStream is = getClass().getResourceAsStream(name);
InputStreamReader isreader=new InputStreamReader(is);//CRASHES HERE WITH NULL POINTER EXCEPTION
BufferedReader br = new BufferedReader(isreader);

但是当我创建一个压缩了 f.fsh 的 JAR 文件并运行它时,它会在创建 InputStreamReader 时崩溃,因为 InputStream 为空。

我已经阅读了一堆关于输入流和 JAR 文件的问题的答案,我从中得到的是我应该使用相对路径,但我已经在这样做了。据我了解 getResourceAsStream() 可以找到相对于项目根目录的文件,这就是我想要的。为什么它在 JAR 中不起作用?出了什么问题,我该如何解决?

它与类路径有关吗?我认为这仅用于包含正在运行的 jar 外部的文件。

我也尝试过,但在输入斜线时仍然失败:

InputStream is = getClass().getResourceAsStream("\\"+name);

我查看了:How to get a path to a resource in a Java JAR file 并发现 JAR 的内容不一定可以作为文件访问。所以我尝试复制相对于 jar 的文件(从 jar 开始的一个目录),但仍然失败。在任何情况下,我都想把我的文件留在罐子里并能够在那里阅读它们。我不知道出了什么问题。

【问题讨论】:

【参考方案1】:
    文件名必须区分大小写 如果文件被移动或复制到 Exclipse 之外,则必须刷新 (F5) 项目浏览器

【讨论】:

【参考方案2】:

如果.. 在从 Eclipse 运行时在 Class.getResourceAsStream() 中工作,则这是 Eclipse 中的一个错误。 Eclipse 和其他 IDE 实现自定义类加载器以在运行时从项目中获取资源。看起来 Eclipse 中的类加载器实现没有对 getResourceAsStream() 方法的输入执行所有必要的验证。在这种情况下,该错误对您有利,但您仍需要重新考虑如何构建资源以使代码在所有情况下都能正常工作。

【讨论】:

谢谢,这是有道理的。我更改了我的文件位置和我的资源所在的位置,它能够克服 jar 中的这个错误。我永远不会想到 Eclipse 有一个对我有利的错误。非常感谢!【参考方案3】:

您不能将..Class.getResourceAsStream() 一起使用。

要在与类相同的包中加载资源f.fsh,请使用SomeClass.class.getResourceAsStream("f.fsh")

要在类包的子包foo.bar中加载资源f.fsh,请使用SomeClass.class.getResourceAsStream("foo/bar/f.fsh")

要在任何包 com.company.foo.bar 中加载资源 f.fsh,请使用 SomeClass.class.getResourceAsStream("/com/company/foo/bar/f.fsh")

这在 getResource() 方法的 javadoc 中有描述,尽管它缺少示例。

【讨论】:

感谢您的回复,我明白您所说的是否在开头添加斜线。它不适用于“..”?当我从 Eclipse 运行它时,它似乎无法理解“..”。但它只是与罐子不兼容?你知道为什么吗? 我什至很惊讶它在从罐子中使用时可以工作。 javadoc 不允许使用 ..。这就是它的设计方式。 刚刚遇到同样的问题。我的猜测是,当从磁盘上的类文件执行时,参数只是被发送(稍微解析)到操作系统函数,因此即使不遵循协议也可以工作。这是用 SE6 btw 测试的。

以上是关于为啥 getResourceAsStream() 可以在 IDE 中工作,但不能在 JAR 中工作?的主要内容,如果未能解决你的问题,请参考以下文章

Class.getResourceAsStream()和ClassLoader.getResourceAsStream()

Class.getResourceAsStream()与ClassLoader.getResourceAsStream()的区别

JAVA 笔记 ClassLoader.getResourceAsStream() 与 Class.getResourceAsStream()的区别

Class.getResourceAsStream和ClassLoader.getResourceAsStream方法

ClassLoader.getResourceAsStream() 与 Class.getResourceAsStream()的区别

getResourceAsStream() 与 FileInputStream