将文件作为InputStream加载的不同方式
有什么区别:
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中。
关于您传递的fileName
如何解释有细微的差异。 基本上,你有2种不同的方法: ClassLoader.getResourceAsStream()
和Class.getResourceAsStream()
。 这两种方法将以不同方式查找资源。
在Class.getResourceAsStream(path)
,该路径被解释为本地到您调用它的类的包的路径。 例如调用, String.getResourceAsStream("myfile.txt")
将在以下位置的类路径中查找文件: "java/lang/myfile.txt"
。 如果你的路径以/
开始,那么它将被视为绝对路径,并且将从类路径的根开始搜索。 因此,调用String.getResourceAsStream("/myfile.txt")
将查看类路径./myfile.txt
中的以下位置。
ClassLoader.getResourceAsStream(path)
将所有路径视为绝对路径。 因此,调用String.getClassLoader().getResourceAsStream("myfile.txt")
和String.getClassLoader().getResourceAsStream("/myfile.txt")
将在以下位置的类路径中查找文件: ./myfile.txt
。
每次我在这篇文章中提到一个位置时,它都可能是文件系统本身的一个位置,或者位于相应的jar文件中,具体取决于您要从中加载资源的Class和/或ClassLoader。
在你的情况下,你从应用服务器加载类,所以你应该使用Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName)
而不是this.getClass().getClassLoader().getResourceAsStream(fileName)
。 this.getClass().getResourceAsStream()
也可以。
阅读这篇文章,了解有关该特定问题的更多详细信息。
警告Tomcat 7及以下用户
这个问题的答案之一指出,我的解释似乎是不正确的Tomcat 7.我试图环顾四周,看看为什么会这样。
所以我查看了Tomcat的几个版本Tomcat的WebAppClassLoader
的源代码。 findResource(String name)
(它完全负责生成所请求资源的URL)的实现在Tomcat 6和Tomcat 7中几乎相同,但在Tomcat 8中不同。
在版本6和7中,实现不会尝试标准化资源名称。 这意味着在这些版本中, classLoader.getResourceAsStream("/resource.txt")
可能不会产生与classLoader.getResourceAsStream("resource.txt")
事件相同的结果,尽管它应该(因为Javadoc指定的)。 [源代码]
但是,在版本8中,资源名称被标准化以确保资源名称的绝对版本是使用的资源名称。 因此,在Tomcat 8中,上述两个调用应始终返回相同的结果。 [源代码]
因此,在8以前的Tomcat版本上使用ClassLoader.getResourceAsStream()
或Class.getResourceAsStream()
时,必须特别小心。并且还必须记住, class.getResourceAsStream("/resource.txt")
实际上调用classLoader.getResourceAsStream("resource.txt")
(领先的/
被剥离)。
使用MyClass.class.getClassLoader().getResourceAsStream(path)
加载与您的代码相关的资源。 使用MyClass.class.getResourceAsStream(path)
作为快捷方式,并将资源打包到您的类包中。
使用Thread.currentThread().getContextClassLoader().getResourceAsStream(path)
来获取作为客户端代码一部分的资源,而不是紧挨调用代码。 你应该小心,因为线程上下文类加载器可以指向任何东西。
普通的旧Java 7上的普通旧式Java,并且没有其他依赖关系证明它们之间的区别...
我把c:temp
file.txt
放在classpath中,并把c:temp
放在classpath中。
只有一种情况是两个电话之间有区别。
class J {
public static void main(String[] a) {
// as "absolute"
// ok
System.err.println(J.class.getResourceAsStream("/file.txt") != null);
// pop
System.err.println(J.class.getClassLoader().getResourceAsStream("/file.txt") != null);
// as relative
// ok
System.err.println(J.class.getResourceAsStream("./file.txt") != null);
// ok
System.err.println(J.class.getClassLoader().getResourceAsStream("./file.txt") != null);
// no path
// ok
System.err.println(J.class.getResourceAsStream("file.txt") != null);
// ok
System.err.println(J.class.getClassLoader().getResourceAsStream("file.txt") != null);
}
}
链接地址: http://www.djcxy.com/p/78369.html