getResourceAsStream()与FileInputStream

我试图加载一个文件在一个Web应用程序,我得到一个FileNotFoundexception,当我使用FileInputStream 。 但是,使用相同的path,我可以加载文件,当我getResourceAsStream() 。 这两种方法有什么区别,为什么一个工作而另一个不工作呢?

java.io.File和consorts在本地磁盘文件系统上运行。 问题的根本原因是java.io中的相对path依赖于当前的工作目录。 即从JVM(在你的情况下:Web服务器的)的目录开始。 例如,这可能是C:\Tomcat\bin或完全不同的东西,但不是 C:\Tomcat\webapps\contextname或任何您所期望的。 在一个正常的Ec​​lipse项目中,这将是C:\Eclipse\workspace\projectname 。 您可以通过以下方式了解当前工作目录:

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

但是,工作目录不能以编程方式控制。 你应该更喜欢在File API中使用绝对path,而不是相对path。 例如C:\full\path\to\file.ext

您不想硬编码或猜测Java(Web)应用程序的绝对path。 这只是可移植性的麻烦(即它在系统X中运行,而不在系统Y中运行)。 通常的做法是将这些types的资源放在类path中 ,或者将它的完整path添加到类path(在像Eclipse这样的src文件夹和“构buildpath”的IDE中)。 这样,您可以通过ClassLoader#getResource()ClassLoader#getResourceAsStream()ClassLoader的帮助下抓取它们。 它可以find相对于类path的“根”的文件,正如你巧合的想通了一样。 在web应用程序(或任何其他使用多个类加载器的应用程序)中,build议使用由Thread.currentThread().getContextClassLoader()返回的Thread.currentThread().getContextClassLoader() ,以便您可以查看webapp上下文的“外部”。

webapps的另一个select是ServletContext#getResource()及其对应的ServletContext#getResourceAsStream() 。 它可以访问位于webapp项目的公共web文件夹中的文件,包括/WEB-INF文件夹。 通过inheritance的getServletContext()方法, ServletContext在Servlet中可用,您可以按原样调用它。

也可以看看:

  • 在何处放置以及如何读取基于servlet的应用程序中的configuration资源文件?
  • servletcontext.getRealPath(“/”)是什么意思,什么时候应该使用它
  • 将上传的文件保存在servlet应用程序中的推荐方法
  • 如何在基于servlet的Web应用程序中暂时保存生成的文件

getResourceAsStream是正确的方法来做它的networking应用程序(如你已经知道)。

原因是,如果您将Web应用程序打包到WAR中,则从文件系统读取文件系统将无法正常工作。 这是打包Web应用程序的正确方法。 这是可移植的,因为您不依赖绝对文件path或应用程序服务器的安装位置。

FileInputStream类直接与底层文件系统一起工作。 如果有问题的文件没有实际存在,它将无法打开它。 getResourceAsStream()方法的工作方式不同。 它尝试使用所调用类的ClassLoader来定位和加载资源。 这使得它能够findembedded到jar文件中的资源。

FileInputStream会将你传递给构造函数的文件path加载到Java进程的工作目录中。 通常在Web容器中,这就像bin文件夹。

getResourceAsStream()会从应用程序的类path加载一个相对的文件path。

classname.getResourceAsStream()通过classname的类加载器加载一个文件。 如果这个类来自一个jar文件,那就是从哪里加载资源。

FileInputStream用于从文件系统中读取文件。