使用类加载器加载文件

2022-09-04 06:38:48

这个问题已经困扰了我一段时间。我必须在我的java应用程序中加载几个文件,到目前为止,我工作的唯一方式是这样的:

URL hsURL;
if(System.getProperty("os.name").toLowerCase().contains("windows")) {
    hsURL = new URL("file:/" + System.getProperty("user.dir") + "/helpsets/helpset.hs");
}
else {
    hsURL = new URL("file://" + System.getProperty("user.dir") + "/helpsets/helpset.hs");
}

但这是丑陋和可怕的。有一段时间,我以为我有这个工作:

hsURL = ClassLoader.getSystemResource("helpsets/helpset.hs");

但是由于某种原因,这不再有效(我一定改变了一些东西,但没有注意到。它返回 null。

我应该使用getResource()而不是getSystemResource()(如果是这样,为什么getSystemResource()是静态的而不是getResource())?

我正在使用eclipse,我尝试将文件夹包含在构建路径(类路径)中,而不是包括它,它似乎没有区别。


答案 1

getSystemResource是静态的,因为它将使用静态可用的系统类装入器。(ClassLoader.getSystemClassLoader)

如果您的资源在类路径中可用,我建议使用或从适当的类中使用,例如ClassLoader.getResource()Class.getResource

Foo.class.getResource("/helpsets/helpset.hs");

(ClassLoader.getResource是“绝对的”; 相对于类的包,除非您以“/”作为前缀。Class.getResource

如果这不起作用,请发布您的应用程序在类路径方面的配置方式以及文件所在的位置。

编辑:我通常发现URL不如一个有用,所以我使用代替.断续器InputStreamgetResourceAsStreamgetResource


答案 2

你在这里提到了几件不同的事情,所以让我们把它们整理一下。

1) 基于 “user.dir” 创建一个 “file:” URL

“user.dir”属性是指当前工作目录 - 用户在启动应用时可能去过的任何位置。此处写入的文件很有可能在两次运行之间消失(因为用户可能从其他目录运行)。

“user.home” 属性引用用户的主目录 -- 该目录在两次运行之间应保持不变。

在任何一种情况下,使用File对象打开文件,不要在创建“file:”URL时捣乱。您不会获得任何好处,并且如您所见,您必须编写混乱的代码才能访问它。

2) 通过类装入器检索资源

这是为了检索与应用程序打包的文件 - 只读文件。如您所见,有多个变体。我更喜欢使用以下内容,因为我假设一个类将想要加载与它一起打包的文件。

InputStream in = this.getClass().getClassLoader().getResourceAsStream(fileName);