Java getResourceAsStream() 与 FileInputStream
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2308188/
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
getResourceAsStream() vs FileInputStream
提问by Vivin Paliath
I was trying to load a file in a webapp, and I was getting a FileNotFound
exception when I used FileInputStream
. However, using the same path, I was able to load the file when I did getResourceAsStream()
.
What is the difference between the two methods, and why does one work while the other doesn't?
我试图在 webapp 中加载一个文件,FileNotFound
当我使用FileInputStream
. 但是,使用相同的路径,我可以在执行getResourceAsStream()
. 这两种方法有什么区别,为什么一种有效而另一种无效?
采纳答案by BalusC
The java.io.File
and consorts acts on the local disk file system. The root cause of your problem is that relativepaths in java.io
are dependent on the current working directory. I.e. the directory from which the JVM (in your case: the webserver's one) is started. This may for example be C:\Tomcat\bin
or something entirely different, but thus notC:\Tomcat\webapps\contextname
or whatever you'd expect it to be. In a normal Eclipse project, that would be C:\Eclipse\workspace\projectname
. You can learn about the current working directory the following way:
在java.io.File
和配偶的行为在本地磁盘文件系统上。问题的根本原因是相对路径java.io
依赖于当前工作目录。即JVM(在您的情况下:网络服务器的)启动的目录。例如,这可能是C:\Tomcat\bin
或完全不同的东西,但因此不是C:\Tomcat\webapps\contextname
或您期望的任何东西。在一个普通的 Eclipse 项目中,这将是C:\Eclipse\workspace\projectname
. 您可以通过以下方式了解当前工作目录:
System.out.println(new File(".").getAbsolutePath());
However, the working directory is in no way programmatically controllable. You should really prefer using absolutepaths in the File
API instead of relative paths. E.g. C:\full\path\to\file.ext
.
但是,工作目录绝不是可编程控制的。您应该更喜欢在API 中使用绝对路径File
而不是相对路径。例如C:\full\path\to\file.ext
。
You don't want to hardcode or guess the absolute path in Java (web)applications. That's only portability trouble (i.e. it runs in system X, but not in system 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). This way you can grab them with help of the ClassLoader
by ClassLoader#getResource()
or 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.
您不想硬编码或猜测 Java (web) 应用程序中的绝对路径。这只是可移植性问题(即它在系统 X 中运行,但不在系统 Y 中运行)。通常的做法是将这些资源放在classpath 中,或者将其完整路径添加到 classpath (在像 Eclipse 这样的 IDE 中,分别是src
文件夹和“构建路径”)。这样您就可以在ClassLoader
by ClassLoader#getResource()
或 的帮助下抓取它们ClassLoader#getResourceAsStream()
。正如您偶然发现的那样,它能够定位相对于类路径的“根”的文件。在 web 应用程序(或任何其他使用多个类加载器的应用程序)中,建议为此使用ClassLoader
返回的as Thread.currentThread().getContextClassLoader()
,以便您也可以查看 webapp 上下文的“外部”。
Another alternative in webapps is the ServletContext#getResource()
and its counterpart ServletContext#getResourceAsStream()
. It is able to access files located in the public web
folder of the webapp project, including the /WEB-INF
folder. The ServletContext
is available in servlets by the inherited getServletContext()
method, you can call it as-is.
webapps 中的另一种选择是ServletContext#getResource()
和它的对应物ServletContext#getResourceAsStream()
。它能够访问位于web
webapp 项目的 public文件夹中的文件,包括该/WEB-INF
文件夹。该ServletContext
是由继承的Servlet可用getServletContext()
的方法,你可以把它原样。
See also:
也可以看看:
回答by matt b
FileInputStream will load a the file path you pass to the constructor as relative from the working directoryof the Java process. Usually in a web container, this is something like the bin
folder.
FileInputStream 将从Java 进程的工作目录加载您传递给构造函数的文件路径作为相对路径。通常在 Web 容器中,这类似于bin
文件夹。
getResourceAsStream()
will load a file path relative from your application's classpath.
getResourceAsStream()
将从您的应用程序的 classpath加载一个相对的文件路径。
回答by Dirk
The FileInputStream
class works directly with the underlying file system. If the file in question is not physically present there, it will fail to open it. The getResourceAsStream()
method works differently. It tries to locate and load the resource using the ClassLoader
of the class it is called on. This enables it to find, for example, resources embedded into jar
files.
本FileInputStream
类直接与底层的文件系统。如果有问题的文件实际上不在那里,它将无法打开它。该getResourceAsStream()
方法的工作方式不同。它尝试使用ClassLoader
它被调用的类的来定位和加载资源。例如,这使它能够找到嵌入到jar
文件中的资源。
回答by Lachlan Roche
classname.getResourceAsStream() loads a file via the classloader of classname. If the class came from a jar file, that is where the resource will be loaded from.
classname.getResourceAsStream() 通过 classname 的类加载器加载文件。如果该类来自 jar 文件,则将从该文件加载资源。
FileInputStream is used to read a file from the filesystem.
FileInputStream 用于从文件系统读取文件。
回答by duffymo
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. This is the proper way to package a web app. It's portable that way, because you aren't dependent on an absolute file path or the location where your app server is installed.
原因是如果您将 Web 应用程序打包在 WAR 中,则无法从文件系统读取。这是打包 Web 应用程序的正确方法。这种方式是可移植的,因为您不依赖于绝对文件路径或应用服务器的安装位置。
回答by Aditya Bhuyan
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. 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.
文件读取 -1. 适用于本地文件系统。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. 3. Ideally good when trying to load files from packaged files like war or jar.
资源读取 -1. 在类路径上工作 2. 尝试在当前或父类加载器类路径中定位文件/资源。3. 尝试从打包文件(如 war 或 jar)加载文件时非常有用。