将文件加载为 InputStream 的不同方式 [英] Different ways of loading a file as an InputStream

查看:23
本文介绍了将文件加载为 InputStream 的不同方式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有什么区别:

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

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

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

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

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

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

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.

推荐答案

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

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

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

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.class.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.class.getResourceAsStream("/myfile.txt") will look at the following location in your class path ./myfile.txt.

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

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

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

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.

在您的情况下,您是从应用服务器加载类,因此您应该使用 Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName) 而不是 this.getClass().getClassLoader().getResourceAsStream(fileName).this.getClass().getResourceAsStream() 也可以使用.

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.

阅读这篇文章有关该特定问题的更多详细信息.

Read this article for more detailed information about that particular problem.

这个问题的一个答案指出,我的解释似乎对 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的WebAppClassLoader的源代码,了解了几个版本的Tomcat.findResource(String name)(最终负责生成请求资源的 URL)的实现在 Tomcat 6 和 Tomcat 7 中几乎相同,但在 Tomcat 8 中不同.

So I've looked at the source code of Tomcat's WebAppClassLoader for 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.

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

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]

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

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 版本上使用 ClassLoader.getResourceAsStream()Class.getResourceAsStream() 时必须格外小心.并且必须还要记住 class.getResourceAsStream("/resource.txt") 实际上调用了 classLoader.getResourceAsStream("resource.txt")(领先的 / 被剥离).

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).

这篇关于将文件加载为 InputStream 的不同方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆