以不同的方式将文件作为InputStream加载

有什么区别:

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

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

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

什么时候比其他人更适合使用?

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

关于如何传递的fileName有细微的差别。 基本上,你有2种不同的方法: ClassLoader.getResourceAsStream()Class.getResourceAsStream() 。 这两种方法将以不同的方式查找资源。

Class.getResourceAsStream(path) ,该path被解释为本地path到您正在调用它的类的包。 例如调用, String.getResourceAsStream("myfile.txt")将在您的类path中的以下位置查找文件: "java/lang/myfile.txt" 。 如果你的path以/开始,那么它将被视为一个绝对path,并将从类path的根开始search。 因此,调用String.getResourceAsStream("/myfile.txt")将查看类path./myfile.txt中的以下位置。

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

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

在你的情况下,你从Application Server中加载类,所以你应该使用Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName)而不是this.getClass().getClassLoader().getResourceAsStream(fileName)this.getClass().getResourceAsStream()也将工作。

请阅读这篇文章 ,了解关于这个问题的更多详细信息。


警告Tomcat 7及以下用户

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

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

在版本6和7中,实现不会尝试规范化资源名称。 这意味着在这些版本中, classLoader.getResourceAsStream("/resource.txt")可能不会产生与classLoader.getResourceAsStream("resource.txt")事件相同的结果,尽pipe它应该(因为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,没有其他的依赖关系certificate了区别…

我把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); } } 

这里的所有答案,以及这个问题的答案都表明,加载绝对URL,比如“/foo/bar.properties”,通过class.getResourceAsStream(String)class.getClassLoader().getResourceAsStream(String)处理。getResourceAsStream class.getClassLoader().getResourceAsStream(String) 。 这不是这种情况,至less不是我的Tomcatconfiguration/版本(目前是7.0.40)。

 MyClass.class.getResourceAsStream("/foo/bar.properties"); // works! MyClass.class.getClassLoader().getResourceAsStream("/foo/bar.properties"); // does NOT work! 

对不起,我绝对没有令人满意的解释,但我猜测,tomcat与类加载程序做脏伎俩和黑魔法,造成差异。 我以前总是使用class.getResourceAsStream(String) ,并没有任何问题。

PS:我也在这里发布

它工作,试试这个:

 InputStream in_s1 = TopBrandData.class.getResourceAsStream("/assets/TopBrands.xml");