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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/676250/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 17:46:11  来源:igfitidea点击:

Different ways of loading a file as an InputStream

javainputstream

提问by zqudlyba

What's the difference between:

有什么区别:

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

and

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

and

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

When are each one more appropriate to use than the others?

什么时候每一种都比其他的更适合使用?

The file that I want to read is in the classpath as my class that reads the file. My class and the file are in the same jar and packaged up in an EAR file, and deployed in WebSphere 6.1.

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

采纳答案by LordOfThePigs

There are subtle differences as to how the fileNameyou are passing is interpreted. Basically, you have 2 different methods: ClassLoader.getResourceAsStream()and Class.getResourceAsStream(). These two methods will locate the resource differently.

关于如何fileName解释您传递的内容存在细微的差异。基本上,您有两种不同的方法:ClassLoader.getResourceAsStream()Class.getResourceAsStream(). 这两种方法将不同地定位资源。

In Class.getResourceAsStream(path), the path is interpreted as a path local to the package of the class you are calling it from. For example calling, String.getResourceAsStream("myfile.txt")will look for a file in your classpath at the following location: "java/lang/myfile.txt". If your path starts with a /, then it will be considered an absolute path, and will start searching from the root of the classpath. So calling String.getResourceAsStream("/myfile.txt")will look at the following location in your class path ./myfile.txt.

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

ClassLoader.getResourceAsStream(path)will consider all paths to be absolute paths. So calling String.getClassLoader().getResourceAsStream("myfile.txt")and String.getClassLoader().getResourceAsStream("/myfile.txt")will both look for a file in your classpath at the following location: ./myfile.txt.

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

Everytime I mention a location in this post, it could be a location in your filesystem itself, or inside the corresponding jar file, depending on the Class and/or ClassLoader you are loading the resource from.

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

In your case, you are loading the class from an Application Server, so your should use Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName)instead of this.getClass().getClassLoader().getResourceAsStream(fileName). this.getClass().getResourceAsStream()will also work.

在你的情况,你是加载从应用服务器类,所以你应该使用Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName)代替this.getClass().getClassLoader().getResourceAsStream(fileName)this.getClass().getResourceAsStream()也会起作用。

Read this articlefor more detailed information about that particular problem.

阅读本文以了解有关该特定问题的更多详细信息。



Warning for users of Tomcat 7 and below

Tomcat 7 及以下版本的用户警告

One of the answers to this question states that my explanation seems to be incorrect for Tomcat 7. I've tried to look around to see why that would be the case.

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

So I've looked at the source code of Tomcat's WebAppClassLoaderfor several versions of Tomcat. The implementation of findResource(String name)(which is utimately responsible for producing the URL to the requested resource) is virtually identical in Tomcat 6 and Tomcat 7, but is different in Tomcat 8.

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

In versions 6 and 7, the implementation does not attempt to normalize the resource name. This means that in these versions, classLoader.getResourceAsStream("/resource.txt")may not produce the same result as classLoader.getResourceAsStream("resource.txt")event though it should (since that what the Javadoc specifies). [source code]

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

In version 8 though, the resource name is normalized to guarantee that the absolute version of the resource name is the one that is used. Therefore, in Tomcat 8, the two calls described above should always return the same result. [source code]

但是在版本 8 中,资源名称被规范化以保证资源名称的绝对版本是所使用的。因此,在 Tomcat 8 中,上面描述的两个调用应该总是返回相同的结果。[源代码]

As a result, you have to be extra careful when using ClassLoader.getResourceAsStream()or Class.getResourceAsStream()on Tomcat versions earlier than 8. And you must also keep in mind that class.getResourceAsStream("/resource.txt")actually calls classLoader.getResourceAsStream("resource.txt")(the leading /is stripped).

因此,在 Tomcat 8 之前的版本上使用ClassLoader.getResourceAsStream()或时必须格外小心Class.getResourceAsStream()。并且您还必须记住class.getResourceAsStream("/resource.txt")实际调用classLoader.getResourceAsStream("resource.txt")(前导/被剥离)。

回答by Tom Hawtin - tackline

Use MyClass.class.getClassLoader().getResourceAsStream(path)to load resource associated with your code. Use MyClass.class.getResourceAsStream(path)as a shortcut, and for resources packaged within your class' package.

使用MyClass.class.getClassLoader().getResourceAsStream(path)与您的代码相关联的负载的资源。使用MyClass.class.getResourceAsStream(path)的快捷方式,并为您的类的包中封装的资源。

Use Thread.currentThread().getContextClassLoader().getResourceAsStream(path)to get resources that are part of client code, not tightly bounds to the calling code. You should be careful with this as the thread context class loader could be pointing at anything.

使用Thread.currentThread().getContextClassLoader().getResourceAsStream(path)来获取在客户端代码的一部分资源,而不是紧紧界给调用代码。你应该小心这一点,因为线程上下文类加载器可能指向任何东西。

回答by Tim Büthe

All these answers around here, as well as the answers in this question, suggest that loading absolute URLs, like "/foo/bar.properties" treated the same by class.getResourceAsStream(String)and class.getClassLoader().getResourceAsStream(String). This is NOT the case, at least not in my Tomcat configuration/version (currently 7.0.40).

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

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

Sorry, I have absolutely no satisfying explanation, but I guess that tomcat does dirty tricks and his black magic with the classloaders and cause the difference. I always used class.getResourceAsStream(String)in the past and haven't had any problems.

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

PS: I also posted this over here

PS:我也贴在这里

回答by Jaspreet Singh

It Works , try out this :

它有效,试试这个:

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

回答by John Lonergan

Plain old Java on plain old Java 7 and no other dependencies demonstrates the difference...

普通旧 Java 7 上的普通旧 Java 并且没有其他依赖项证明了区别......

I put file.txtin c:\temp\and I put c:\temp\on the classpath.

我把file.txtc:\temp\我把c:\temp\在类路径中。

There is only one case where there is a difference between the two call.

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

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

回答by António Almeida

After trying some ways to load the file with no success, I remembered I could use FileInputStream, which worked perfectly.

在尝试了一些加载文件但没有成功的方法后,我记得我可以使用FileInputStream,它工作得很好。

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

This is another way to read a file into an InputStream, it reads the file from the currently running folder.

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