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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 05:56:40  来源:igfitidea点击:

getResourceAsStream() vs FileInputStream

javafile-ioweb-applicationsfileinputstream

提问by Vivin Paliath

I was trying to load a file in a webapp, and I was getting a FileNotFoundexception 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.Fileand consorts acts on the local disk file system. The root cause of your problem is that relativepaths in java.ioare 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\binor something entirely different, but thus notC:\Tomcat\webapps\contextnameor 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 FileAPI 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 srcfolder and the "build path" respectively). This way you can grab them with help of the ClassLoaderby 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 ClassLoaderas 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文件夹和“构建路径”)。这样您就可以在ClassLoaderby 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 webfolder of the webapp project, including the /WEB-INFfolder. The ServletContextis available in servlets by the inherited getServletContext()method, you can call it as-is.

webapps 中的另一种选择是ServletContext#getResource()和它的对应物ServletContext#getResourceAsStream()。它能够访问位于webwebapp 项目的 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 binfolder.

FileInputStream 将从Java 进程的工作目录加载您传递给构造函数的文件路径作为相对路径。通常在 Web 容器中,这类似于bin文件夹。

getResourceAsStream()will load a file path relative from your application's classpath.

getResourceAsStream()将从您的应用程序的 classpath加载一个相对的文件路径。

回答by Dirk

The FileInputStreamclass 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 ClassLoaderof the class it is called on. This enables it to find, for example, resources embedded into jarfiles.

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

getResourceAsStreamis 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)加载文件时非常有用。