加载文件为InputStream的不同方法
加载文件为InputStream的不同方法
如下是三种方式的区别:
1. InputStream is = this.getClass().getClassLoader().getResourceAsStream(fileName)
这种方式使用当前类的类加载器来获取文件的输入流。文件必须在类路径下。
2. InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName)
这种方式使用当前线程的上下文类加载器来获取文件的输入流。文件必须在类路径下。
3. InputStream is = this.getClass().getResourceAsStream(fileName)
这种方式使用当前类来获取文件的输入流。文件必须在类所在的包路径下。
在上述情况中,每种方式在何时使用更为合适呢?
当文件位于类路径下并且你想要使用当前类的类加载器时,第一种方式更为合适。
当文件位于类路径下并且你想要使用当前线程的上下文类加载器时,第二种方式更为合适。
当文件位于类所在的包路径下时,第三种方式更为合适。
在你的情况中,由于文件在类路径下,你可以使用第一种或第二种方式。
不同的方法加载文件作为InputStream的方式
问题的原因:不同的方法(ClassLoader.getResourceAsStream()和Class.getResourceAsStream())在解释传递的文件名(fileName)时存在微妙的差异,它们会以不同的方式定位资源。
解决方法:根据具体的情况选择合适的方法来加载文件。在加载类时,如果是从应用服务器中加载类,则应使用Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName)方法或者this.getClass().getResourceAsStream(fileName)方法。
具体解释如下:
- Class.getResourceAsStream(path)方法中,路径(path)被解释为相对于调用该方法的类的包的本地路径。例如,调用String.class.getResourceAsStream("myfile.txt")将在classpath下的以下位置查找文件:"java/lang/myfile.txt"。如果路径以斜杠(/)开头,则被视为绝对路径,并从classpath的根目录开始搜索。因此,调用String.class.getResourceAsStream("/myfile.txt")将在classpath下的以下位置查找文件:"./myfile.txt"。
- ClassLoader.getResourceAsStream(path)方法将所有路径视为绝对路径。因此,调用String.class.getClassLoader().getResourceAsStream("myfile.txt")和String.class.getClassLoader().getResourceAsStream("/myfile.txt")都将在classpath下的以下位置查找文件:"./myfile.txt"。
需要注意的是,本文中提到的位置可能是文件系统本身的位置,也可能是对应jar文件中的位置,这取决于加载资源的类和/或ClassLoader。
对于Tomcat 7及以下版本的用户的警告:
本文中的解释似乎对于Tomcat 7不正确。查看了Tomcat的WebAppClassLoader的源代码,发现在Tomcat 6和Tomcat 7中,findResource(String name)方法的实现(负责生成所请求资源的URL)几乎相同,但在Tomcat 8中有所不同。
在Tomcat 6和Tomcat 7中,该实现不会尝试规范化资源名。这意味着在这些版本中,classLoader.getResourceAsStream("/resource.txt")可能与classLoader.getResourceAsStream("resource.txt")的结果不同,尽管根据Javadoc的规定,它们应该是相同的。
然而,在Tomcat 8中,资源名被规范化,以确保使用的是绝对版本的资源名。因此,在Tomcat 8中,上述两个调用应始终返回相同的结果。
因此,在使用ClassLoader.getResourceAsStream()或Class.getResourceAsStream()时,对于早于Tomcat 8的版本,必须特别小心。还必须记住,class.getResourceAsStream("/resource.txt")实际上调用的是classLoader.getResourceAsStream("resource.txt")(前导的斜杠被去除)。
至于“getClass().getResourceAsStream("/myfile.txt")”和“getClassLoader().getResourceAsStream("/myfile.txt")”是否有不同行为的问题:
它们的行为是相同的。实际上,Class.getResourceAsStream的javadoc中写道:“此方法委托给该对象的类加载器”,然后给出了一系列规则,说明在委托给类加载器之前如何将相对路径转换为绝对路径。
查看实际的源代码。如果提供了绝对路径,则Class.getResourceAsStream会去掉前导斜杠。
这使得它的行为与ClassLoader.getResourceAsStream()完全相同,因为后者将所有路径解释为绝对路径,无论它们是否以前导斜杠开头。因此,只要路径是绝对的,两种方法的行为是相同的。如果路径是相对的,则行为会有所不同。
关于“getClassLoader()”和“String”的问题,应该是一个错误或需要修改。应该将“String.getResourceAsStream(..)”更正为“String.class.getResourceAsStream(..)”。同样,对于“String.getClassLoader()”,应该更正为“String.class.getClassLoader()”。
以上就是关于不同的方法加载文件作为InputStream的方式的原因和解决方法的整理。
不同的加载文件作为InputStream的方法
在普通的Java 7上,没有其他依赖项,演示了不同的方法之间的区别...
我把file.txt放在c:\temp\中,并把c:\temp\放在类路径上。
只有一种情况下两种调用之间存在差异。
class J { public static void main(String[] a) { // 作为"绝对路径" // 正常 System.err.println(J.class.getResourceAsStream("/file.txt") != null); // 报错 System.err.println(J.class.getClassLoader().getResourceAsStream("/file.txt") != null); // 作为相对路径 // 正常 System.err.println(J.class.getResourceAsStream("./file.txt") != null); // 正常 System.err.println(J.class.getClassLoader().getResourceAsStream("./file.txt") != null); // 没有路径 // 正常 System.err.println(J.class.getResourceAsStream("file.txt") != null); // 正常 System.err.println(J.class.getClassLoader().getResourceAsStream("file.txt") != null); } }
非常感谢,对我来说只有'J.class.getResourceAsStream("file.txt")'起作用。
不同的加载文件为InputStream的方式
在Java中,有多种方式可以将文件加载为InputStream。但是,不同的方式可能会导致不同的问题和解决方案。
问题的原因:
问题的原因在于不同的加载方式可能会导致加载的资源与代码的关联性不同,从而导致资源加载的错误或不一致。
解决方法:
解决方法是根据不同的情况选择合适的加载方式。下面是几种常见的加载方式以及解决方法:
1. 使用MyClass.class.getClassLoader().getResourceAsStream(path)
加载与代码相关的资源。这是最常见的加载资源的方式。它将返回与指定路径相关联的资源的InputStream。使用这种方式加载资源时,要确保资源与代码位于同一目录下,或者在类路径中可以找到资源。
2. 使用MyClass.class.getResourceAsStream(path)
作为一种快捷方式,用于加载与类所在包中打包的资源。这种方式可以更简便地加载与类所在包相关的资源。使用这种方式时,要确保资源与类在同一个包中,并且在类路径中可以找到资源。
3. 使用Thread.currentThread().getContextClassLoader().getResourceAsStream(path)
获取与客户端代码相关联的资源,而不是与调用代码紧密绑定的资源。这种方式可以用于加载与客户端代码相关的资源,但要注意线程上下文类加载器可能指向任何内容。在使用这种方式时要小心,确保线程上下文类加载器指向正确的资源。
根据不同的情况选择合适的加载方式可以解决加载文件为InputStream时可能出现的问题。通过选择正确的加载方式,可以确保资源与代码的关联性正确,从而避免资源加载错误或不一致的问题。