简体   繁体   English

getResourceAsStream()与FileInputStream

[英]getResourceAsStream() vs FileInputStream

I was trying to load a file in a webapp, and I was getting a FileNotFound exception when I used FileInputStream . 我试图在Webapp中加载文件,并且在使用FileInputStream时遇到FileNotFound异常。 However, using the same path, I was able to load the file when I did getResourceAsStream() . 但是,使用相同的路径,当我执行getResourceAsStream()时,便能够加载文件。 What is the difference between the two methods, and why does one work while the other doesn't? 两种方法有什么区别,为什么一种方法有效而另一种无效?

The java.io.File and consorts acts on the local disk file system. java.io.File和consorts作用于本地磁盘文件系统。 The root cause of your problem is that relative paths in java.io are dependent on the current working directory. 问题的根本原因是java.io中的相对路径取决于当前的工作目录。 Ie the directory from which the JVM (in your case: the webserver's one) is started. 即启动JVM(在您的情况下为:Web服务器的目录)的目录。 This may for example be C:\\Tomcat\\bin or something entirely different, but thus not C:\\Tomcat\\webapps\\contextname or whatever you'd expect it to be. 例如,这可能是C:\\Tomcat\\bin或完全不同的东西,但不是 C:\\Tomcat\\webapps\\contextname或您希望的任何名称。 In a normal Eclipse project, that would be C:\\Eclipse\\workspace\\projectname . 在普通的Eclipse项目中,它将是C:\\Eclipse\\workspace\\projectname You can learn about the current working directory the following way: 您可以通过以下方式了解当前工作目录:

System.out.println(new File(".").getAbsolutePath());

However, the working directory is in no way programmatically controllable. 但是,工作目录绝不是以编程方式可控制的。 You should really prefer using absolute paths in the File API instead of relative paths. 您确实应该更喜欢在File API中使用绝对路径,而不是相对路径。 Eg C:\\full\\path\\to\\file.ext . 例如C:\\full\\path\\to\\file.ext

You don't want to hardcode or guess the absolute path in Java (web)applications. 您不想硬编码或猜测Java(Web)应用程序中的绝对路径。 That's only portability trouble (ie it runs in system X, but not in system Y). 那只是可移植性的麻烦(即它在系统X中运行,而不在系统Y中运行)。 The normal practice is to place those kind of resources in the classpath , or to add its full path to the classpath (in an IDE like Eclipse that's the src folder and the "build path" respectively). 通常的做法是将此类资源放置在类路径中 ,或将其完整路径添加到类路径(在像Eclipse这样的IDE中,分别是src文件夹和“构建路径”)。 This way you can grab them with help of the ClassLoader by ClassLoader#getResource() or ClassLoader#getResourceAsStream() . 这样,您可以在ClassLoader的帮助下通过ClassLoader#getResource()ClassLoader#getResourceAsStream()来捕获它们。 It is able to locate files relative to the "root" of the classpath, as you by coincidence figured out. 正如您偶然发现的那样,它能够相对于类路径的“根”定位文件。 In webapplications (or any other application which uses multiple classloaders) it's recommend to use the ClassLoader as returned by Thread.currentThread().getContextClassLoader() for this so you can look "outside" the webapp context as well. 在web应用(或者使用多个类加载器的任何其他应用程序),它是推荐使用ClassLoader由返回Thread.currentThread().getContextClassLoader()这个,所以你可以看看“外面” webapp的背景下也是如此。

Another alternative in webapps is the ServletContext#getResource() and its counterpart ServletContext#getResourceAsStream() . webapps中的另一种选择是ServletContext#getResource()及其对应的ServletContext#getResourceAsStream() It is able to access files located in the public web folder of the webapp project, including the /WEB-INF folder. 它能够访问位于webapp项目的公共web文件夹中的文件,包括/WEB-INF文件夹。 The ServletContext is available in servlets by the inherited getServletContext() method, you can call it as-is. ServletContext可通过继承的getServletContext()方法在Servlet中使用,您可以按原样调用它。

See also: 也可以看看:

getResourceAsStream is the right way to do it for web apps (as you already learned). getResourceAsStream是用于Web应用程序的正确方法(如您所知)。

The reason is that reading from the file system cannot work if you package your web app in a WAR. 原因是,如果将Web应用程序打包在WAR中,则无法从文件系统进行读取。 This is the proper way to package a web app. 这是打包Web应用程序的正确方法。 It's portable that way, because you aren't dependent on an absolute file path or the location where your app server is installed. 这种方式可移植,因为您不依赖于绝对文件路径或应用服务器的安装位置。

FileInputStream will load a the file path you pass to the constructor as relative from the working directory of the Java process. FileInputStream将从Java进程的工作目录中加载相对于您传递给构造函数的文件路径。 Usually in a web container, this is something like the bin folder. 通常在Web容器中,这类似于bin文件夹。

getResourceAsStream() will load a file path relative from your application's classpath . getResourceAsStream()将从应用程序的classpath加载相对的文件路径。

The FileInputStream class works directly with the underlying file system. FileInputStream类直接与基础文件系统一起使用。 If the file in question is not physically present there, it will fail to open it. 如果该文件实际上不在此处,它将无法打开它。 The getResourceAsStream() method works differently. getResourceAsStream()方法的工作方式不同。 It tries to locate and load the resource using the ClassLoader of the class it is called on. 它尝试使用被调用的类的ClassLoader查找和加载资源。 This enables it to find, for example, resources embedded into jar files. 例如,这使它能够查找嵌入jar文件中的资源。

classname.getResourceAsStream() loads a file via the classloader of classname. classname.getResourceAsStream()通过classname的类加载器加载文件。 If the class came from a jar file, that is where the resource will be loaded from. 如果该类来自jar文件,则将从那里加载资源。

FileInputStream is used to read a file from the filesystem. FileInputStream用于从文件系统读取文件。

I am here by separating both the usages by marking them as File Read(java.io) and Resource Read(ClassLoader.getResourceAsStream()). 我在这里通过将这两种用法标记为File Read(java.io)和Resource Read(ClassLoader.getResourceAsStream())来分开使用。

File Read - 1. Works on local file system. 文件读取-1 .在本地文件系统上工作。 2. Tries to locate the file requested from current JVM launched directory as root 3. Ideally good when using files for processing in a pre-determined location like,/dev/files or C:\\Data. 2.尝试将当前JVM启动目录中请求的文件作为根目录定位。3.在预定位置使用文件进行处理时,如/ dev / files或C:\\ Data,则非常理想。

Resource Read - 1. Works on class path 2. Tries to locate the file/resource in current or parent classloader classpath. 资源读取-1 .在类路径上工作。2.尝试在当前或父类加载器的类路径中找到文件/资源​​。 3. Ideally good when trying to load files from packaged files like war or jar. 3.尝试从打包文件(如war或jar)中加载文件时非常理想。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM