将文件加载为InputStream的不同方法
传递的文件名的解释存在细微的差异。基本上有两种不同的方法:ClassLoader.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 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 中应始终产生相同的结果。 [源代码]
因此,在 Tomcat 8 之前的版本上使用 ClassLoader.getResourceAsStream() 或 Class.getResourceAsStream() 时需要格外小心。并且您还必须记住,class.getResourceAsStream("/resource.txt") 实际上调用了 classLoader.getResourceAsStream("resource.txt")(删除了前导 /)。
以上是将文件作为输入流加载时,'ClassLoader.getResourceAsStream()”和'Class.getResourceAsStream()”有何不同?的详细内容。更多信息请关注PHP中文网其他相关文章!