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

Java 将文件作为InputStream加载的不同方式,java,inputstream,Java,Inputstream,这两者之间的区别是什么: InputStream is = this.getClass().getClassLoader().getResourceAsStream(fileName) 及 及 什么时候每一个都比其他更适合使用 我要读取的文件在类路径中作为读取该文件的类。我的类和该文件位于同一个jar中,打包在一个EAR文件中,并部署在WebSphere 6.1中。对于您传递的文件名的解释方式存在细微的差异。基本上,您有两种不同的方法:ClassLoader.getResourceAsStre

这两者之间的区别是什么:

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

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


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

对于您传递的
文件名的解释方式存在细微的差异。基本上,您有两种不同的方法:
ClassLoader.getResourceAsStream()
Class.getResourceAsStream()
。这两种方法将以不同的方式定位资源

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

<> >代码>类加载器.GETRealSuffSturnScript(PATH)< /C> >将考虑所有路径为绝对路径。因此,调用
String.class.getClassLoader().getResourceAsStream(“myfile.txt”)
String.class.getClassLoader().getResourceAsStream(“/myfile.txt”)
都会在类路径中的以下位置查找文件:
/myfile.txt

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

在本例中,您是从应用程序服务器加载类,因此应该使用
Thread.currentThread().getContextClassLoader().getResourceAsStream(文件名)
,而不是
this.getClass().getClassLoader().getResourceAsStream(文件名)
this.getClass().getResourceAsStream()
也可以使用

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


Tomcat 7及以下版本用户的警告 这个问题的一个答案是,对于Tomcat7,我的解释似乎不正确。我试着四处看看为什么会这样

因此,我查看了Tomcat的几个版本的
WebAppClassLoader
的源代码。
findResource(字符串名)
(它实际上负责生成请求资源的URL)的实现在Tomcat 6和Tomcat 7中几乎相同,但在Tomcat 8中不同

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

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


因此,在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)
获取作为客户端代码一部分的资源,而不是与调用代码紧密绑定的资源。您应该注意这一点,因为线程上下文类加载器可能指向任何东西。

这里的所有答案以及中的答案都表明,加载绝对URL,如“/foo/bar.properties”,与
class.getResourceAsStream(String)
class.getClassLoader().getResourceAsStream()一样(String)
。情况并非如此,至少在我的Tomcat配置/版本(当前为7.0.40)中不是这样

很抱歉,我绝对没有令人满意的解释,但我猜tomcat对类加载器使用了肮脏的把戏和他的黑魔法,并导致了差异。我过去一直使用
class.getResourceAsStream(String)
,没有任何问题


PS:我也在上面发布了这篇文章。它很有效,请尝试一下:

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

在纯旧Java 7上的纯旧Java和没有其他依赖项证明了这一区别

我将
file.txt
放在
c:\temp\
中,并将
c:\temp\
放在类路径上

只有一种情况下,两个调用之间存在差异

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

在尝试了一些加载文件的方法但没有成功之后,我想起我可以使用
FileInputStream
,这非常有效

InputStream is = new FileInputStream("file.txt");

这是将文件读入
InputStream
的另一种方法,它从当前运行的文件夹中读取文件。

我非常确定
getClass().getResourceAsStream(“/myfile.txt”)
的行为与
getClassLoader().getResourceAsStream(/myfile.txt”)不同
@BrianGordon:它们的行为没有差异。实际上,的javadoc说了以下内容:“这个方法委托给这个对象的类加载器。”,然后给出了一系列关于它如何转换的规则
InputStream in_s1 =   TopBrandData.class.getResourceAsStream("/assets/TopBrands.xml");
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); 
  }
}
InputStream is = new FileInputStream("file.txt");