将文件作为输入流加载的不同方法

发布于 2024-07-15 20:01:01 字数 460 浏览 3 评论 0原文

之间有什么区别?

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

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

何时

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

比其他更适合使用?

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

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

感性 2024-07-22 20:01:01

您传递的 fileName 的解释方式存在细微差别。 基本上,您有两种不同的方法: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 文件中的位置,具体取决于您从中加载资源的类和/或类加载器。

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

阅读本文了解更多详细信息关于那个特定问题。


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

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

因此,我查看了 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") (前导 / 被剥离)。

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.

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

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.

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.


Warning for users of Tomcat 7 and below

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.

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.

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]

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]

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

裂开嘴轻声笑有多痛 2024-07-22 20:01:01

使用 MyClass.class.getClassLoader().getResourceAsStream(path) 加载与您的代码关联的资源。 使用 MyClass.class.getResourceAsStream(path) 作为快捷方式,并获取打包在类包中的资源。

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

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.

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.

他夏了夏天 2024-07-22 20:01:01

普通旧式 Java 运行在普通旧式 Java 7 上,没有其他依赖项表明了差异...

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

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

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

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); 
  }
}
海夕 2024-07-22 20:01:01

这里的所有这些答案,以及这个问题中的答案,都建议加载绝对 URL,例如“/foo/bar.html”。 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!

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

PS:我还在这里发布了这个

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

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.

PS: I also posted this over here

孤芳又自赏 2024-07-22 20:01:01

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

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

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

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

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.

暖伴 2024-07-22 20:01:01

它有效,试试这个:

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

It Works , try out this :

InputStream in_s1 =   TopBrandData.class.getResourceAsStream("/assets/TopBrands.xml");
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文