将文件作为输入流加载的不同方式

2022-08-31 05:44:47

有什么区别:

InputStream is = this.getClass().getClassLoader().getResourceAsStream(fileName)

InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName)

InputStream is = this.getClass().getResourceAsStream(fileName)

什么时候每一个都比其他的更适合使用?

我要读取的文件在类路径中,作为读取该文件的类。我的类和文件位于同一个 jar 中,并打包在 EAR 文件中,并部署在 WebSphere 6.1 中。


答案 1

关于如何解释你通过的,存在细微的区别。基本上,您有 2 种不同的方法:和 。这两种方法将以不同的方式定位资源。fileNameClassLoader.getResourceAsStream()Class.getResourceAsStream()

在 中,该路径被解释为要从中调用它的类的包的本地路径。例如,调用 ,将在类路径中的以下位置查找文件:.如果路径以 开头,则它将被视为绝对路径,并将从类路径的根目录开始搜索。因此,调用将查看类路径中的以下位置。Class.getResourceAsStream(path)String.class.getResourceAsStream("myfile.txt")"java/lang/myfile.txt"/String.class.getResourceAsStream("/myfile.txt")./myfile.txt

ClassLoader.getResourceAsStream(path)会将所有路径视为绝对路径。因此,调用 和 都将在类路径中的以下位置查找文件:.String.class.getClassLoader().getResourceAsStream("myfile.txt")String.class.getClassLoader().getResourceAsStream("/myfile.txt")./myfile.txt

每次我在这篇文章中提到一个位置时,它可能是文件系统本身的位置,也可能是相应的jar文件中的位置,具体取决于您从中加载资源的类和/或ClassLoader。

在本例中,您是从应用程序服务器装入类的,因此应使用 代替 。 也会工作。Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName)this.getClass().getClassLoader().getResourceAsStream(fileName)this.getClass().getResourceAsStream()

有关特定问题的更多详细信息,请阅读本文。


针对Tomcat 7及以下版本的用户的警告

这个问题的答案之一是,我的解释似乎对Tomcat 7来说是不正确的。我试图环顾四周,看看为什么会这样。

所以我看了Tomcat的几个版本的Tomcat的源代码。的实现(它负责生成所请求资源的 URL)在 Tomcat 6 和 Tomcat 7 中实际上是相同的,但在 Tomcat 8 中是不同的。WebAppClassLoaderfindResource(String name)

在版本 6 和 7 中,实现不会尝试规范化资源名称。这意味着在这些版本中,可能不会产生与事件相同的结果,尽管它应该产生(因为这是Javadoc指定的)。[源代码]classLoader.getResourceAsStream("/resource.txt")classLoader.getResourceAsStream("resource.txt")

但是,在版本 8 中,资源名称被规范化,以保证资源名称的绝对版本是所使用的版本。因此,在 Tomcat 8 中,上述两个调用应始终返回相同的结果。[源代码]

因此,在使用或使用早于8的Tomcat版本时,您必须格外小心。您还必须记住,实际调用(前导被剥离)。ClassLoader.getResourceAsStream()Class.getResourceAsStream()class.getResourceAsStream("/resource.txt")classLoader.getResourceAsStream("resource.txt")/


答案 2

用于加载与代码关联的资源。用作快捷方式,并用于打包在类包中的资源。MyClass.class.getClassLoader().getResourceAsStream(path)MyClass.class.getResourceAsStream(path)

用于获取作为客户端代码一部分的资源,而不是与调用代码紧密绑定的资源。您应该小心这一点,因为线程上下文类装入器可能指向任何内容。Thread.currentThread().getContextClassLoader().getResourceAsStream(path)


推荐