简体   繁体   English

Java:getClass().getResource().toURI() 与 getClass().getResourceAsStream()

[英]Java : getClass().getResource().toURI() Vs getClass().getResourceAsStream()

I have a java multiple modules sbt project and some of them contains a resources folder.我有一个java多个模块sbt项目,其中一些包含resources文件夹。

module-1
  resources
    template.xls
module-2
  resources
    other.xls

After packaging I got:打包后我得到:

lib/module-1.jar
lib/module-2.jar

And I run my program like any other java application: java -cp "lib/*" MainClass .我像其他任何 java 应用程序一样运行我的程序: java -cp "lib/*" MainClass

My problem is accessing the template.xls from module-2.jar .我的问题是从module-2.jar访问template.xls

At first, I've tried the lines below to get my template:起初,我尝试了以下几行来获取我的模板:

URI template = getClass().getResource("/template.xls").toURI();
Files.newInputStream(Paths.get(template), StandardOpenOption.READ);

In development mode it works.开发模式下它可以工作。 But not on the server (after deployment), it cannot find the resource.但不在服务器上(部署后),它找不到资源。

java.nio.file.FileSystemNotFoundException: null [jar:file:/.../lib/module-1.jar./template.xls] java.nio.file.FileSystemNotFoundException: null [jar:file:/.../lib/module-1.jar./template.xls]

After some research I modified my accessing code like the following to get it works in both modes (development and deployed):经过一些研究,我修改了我的访问代码,如下所示,使其在两种模式(开发和部署)下都能正常工作:

InputStream templateIS = getClass().getResourceAsStream("/template.xls");

I cannot understand why !我不明白为什么!

What is the difference between the two methods?这两种方法有什么区别?

Files.newInputStream , as the name suggests, can open files. Files.newInputStream ,顾名思义,可以打开文件。 It cannot open anything else.它无法打开其他任何东西。 It's just for files.它只是用于文件。

The concept of an InputStream is much more abstract. InputStream的概念要抽象得多。 When you open a file for reading, you get an inputstream, yup.当你打开一个文件进行阅读时,你会得到一个输入流,是的。 But you also get inputstreams for many other things: Reading from a network connection;但是你也可以得到很多其他的输入流:从网络连接读取; reading the unpacked contents of zip files.读取 zip 文件的解压缩内容。 Reading the output of a decryption operation.读取 output 的一个解密操作。 The name says it all really: It's input, and it's a stream of data.这个名字真的说明了一切:它是输入,它是数据的 stream。 Which applies to so much more than 'file on a filesystem'.这不仅仅适用于“文件系统上的文件”。

Paths.get(template) produces a path object, which represents a file on the file system. Paths.get(template)产生一个路径 object,它代表文件系统上的一个文件。 If template is derived from a URI, this does not work unless the URI that you have so happens to be a URI to a file object;如果template是从 URI 派生的,则这不起作用,除非您拥有的 URI 恰好是文件 object 的 URI; most URIs are not to file objects.大多数 URI 不用于文件对象。

Putting it all together, in your first sample, you find a resource on the classpath (which can be files, but don't have to be. For example, they could be entries in a jar file), you then ask its URI, feed it to the Paths API to turn it into a Path object, and then ask the Files API to turn this into an InputStream, which only works if the URI represents a file.综上所述,在您的第一个示例中,您在类路径中找到了一个资源(可以是文件,但不一定是。例如,它们可以是 jar 文件中的条目),然后您询问其 URI,将其输入到路径 API 以将其转换为路径 object,然后要求文件 API 将其转换为 InputStream,这仅在 URI 表示文件时才有效。

In the second snippet, you just ask the classloader system to get you an inputstream.在第二个片段中,您只需要求类加载器系统为您获取输入流。 It knows how to do that (after all, java has to load those class files.), If the resource you're asking for so happens to be represented by a file, it's going to do, internally: more or less the same thing as your first snippet.它知道如何做到这一点(毕竟,java 必须加载那些 class 文件。),如果您要求的资源恰好由文件表示,它会在内部执行:或多或少相同的事情作为你的第一个片段。 Use the Files API to open the file for reading, But if it's anything else, it knows how to do that too – it also knows how to get resources across a network, from inside jar files, generated on-the-fly – the concept of class loading (which is what class.getResource lets you access) is abstracted away.使用文件 API 打开文件进行读取,但如果是其他内容,它也知道如何执行此操作 - 它还知道如何通过网络从 jar 文件中获取资源,即时生成 - 概念class 加载(这是class.getResource允许您访问的内容)被抽象掉。

NB: You're using it wrong.注意:你用错了。 The proper way is ClassYouAreWritingIn.class.getResource and ClassYouAreWritingIn.class.getResourceAsStream ;正确的方法是ClassYouAreWritingIn.class.getResourceClassYouAreWritingIn.class.getResourceAsStream getClass().getResource is not correct; getClass().getResource不正确; that breaks when subclassing, whereas the correct form doesn't.子类化时会中断,而正确的形式不会。

Your first scenario doesn't work because the template.xls is packaged within a jar file.您的第一个方案不起作用,因为template.xls打包jar 文件中。 It's not a file on the filesystem (whereas it likely is in your development env prior to packaging as a file).它不是文件系统上的文件(而在打包为文件之前它可能在您的开发环境中)。 As such the Files API can't find it.因此Files API 找不到它。

Class.getResourceAsStream() makes use of the classloading mechanism, and the class (obviously) is loaded from the .jar file. Class.getResourceAsStream()利用类加载机制,class(显然)是从.jar文件加载的。

From docs ,文档

The method getResource() returns a URL for the resource. getResource() 方法返回资源的 URL。 The URL (and its representation) is specific to the implementation and the JVM (that is, the URL obtained in one runtime instance may not work in another). URL(及其表示)特定于实现,而在一个运行时实例中获得的 JVM(即 URL)可能无法在另一个运行时实例中工作。 Its protocol is usually specific to the ClassLoader loading the resource.它的协议通常特定于加载资源的 ClassLoader。 If the resource does not exist or is not visible due to security considerations, the methods return null.如果资源不存在或出于安全考虑不可见,则方法返回 null。

If the client code wants to read the contents of the resource as an InputStream, it can apply the openStream() method on the URL.如果客户端代码想要将资源的内容作为 InputStream 读取,它可以在 URL 上应用 openStream() 方法。 This is common enough to justify adding getResourceAsStream() to Class and ClassLoader.这很常见,足以证明将 getResourceAsStream() 添加到 Class 和 ClassLoader 是合理的。 getResourceAsStream() the same as calling getResource().openStream(), except that getResourceAsStream() catches IO exceptions returns a null InputStream. getResourceAsStream() 与调用 getResource().openStream() 相同,只是 getResourceAsStream() 捕获 IO 异常返回 null InputStream。

So, getResourceAsStream() the same as calling getResource().openStream() , except that getResourceAsStream() catches IO exceptions returns a null InputStream.因此, getResourceAsStream()与调用getResource().openStream()相同,只是getResourceAsStream()捕获 IO 异常返回 null InputStream。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 getResourceAsStream类与getClass() - getResourceAsStream class vs getClass() 等价于Jar中的this.getClass()。getClassLoader()。getResource(“。”)。toURI() - Equivalent of this.getClass().getClassLoader().getResource(“.”).toURI() from within a Jar 使用Java Web Start获取getClass()。getResource() - getClass().getResource() with Java Web Start java jar getClass().getClassLoader().getResourceAsStream 返回空指针异常 - java jar getClass().getClassLoader().getResourceAsStream return nullpointerexception Java OutputStream 等价于 getClass().getClassLoader().getResourceAsStream() - Java OutputStream equivalent to getClass().getClassLoader().getResourceAsStream() java netbeans getClass()。getResource(filename)返回null - java netbeans getClass().getResource(filename) return null 返回空指针的 png 上的 Java getClass().getResource - Java getClass().getResource on a png returning Null Pointer Java的getClass()的最佳国际替代品.getResource() - Best international alternative to Java's getClass().getResource() Java getClass()。getResource(string)在NetBeans路径上不起作用 - Java getClass().getResource(string) not working on netbeans path Java getClass().getResource("file") 导致 NullPointerException - Java getClass().getResource("file") leads to NullPointerException
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM