我试图在webapp中加载文件,而FileNotFound使用时却出现异常FileInputStream。但是,使用相同的路径时,我能够加载文件getResourceAsStream()。两种方法有什么区别,为什么一种方法有效而另一种无效?
webapp
FileNotFound
FileInputStream
getResourceAsStream()
在java.io.File和配偶的行为在本地磁盘文件系统上。问题的根本原因是其中的相对路径java.io取决于当前工作目录。即从中启动JVM(在你的情况下为:Web服务器的目录)的目录。例如,这可能是C:\Tomcat\bin或完全不同的东西,但是却并非 如此,C:\Tomcat\webapps\contextname或者你期望的是什么。在正常的Eclipse项目中,该值为C:\Eclipse\workspace\projectname。你可以通过以下方式了解当前工作目录:
java.io.File
java.io
C:\Tomcat\bin
C:\Tomcat\webapps\contextname
Eclipse
C:\Eclipse\workspace\projectname
System.out.println(new File(".").getAbsolutePath());
但是,工作目录绝不是以编程方式可控制的。你确实应该更喜欢在API中使用绝对路径,File而不是相对路径。例如C:\full\path\to\file.ext。
C:\full\path\to\file.ext
你不想硬编码或猜测Java(Web)应用程序中的绝对路径。那只是可移植性的麻烦(即它在系统X中运行,而不在系统Y中运行)。通常的做法是将此类资源放置在类路径中,或将其完整路径添加到类路径(在像Eclipse这样的IDE中,分别是src文件夹和“构建路径”)。这样,你可以借助ClassLoaderby ClassLoader#getResource()或抓住它们ClassLoader#getResourceAsStream()。巧合的是,它能够相对于类路径的“根”定位文件。在Web应用程序(或使用多个类加载器的任何其他应用程序)中,建议为此使用ClassLoader返回的as Thread.currentThread().getContextClassLoader(),以便你也可以在webapp上下文之外查找。
ClassLoaderby ClassLoader#getResource()
ClassLoader#getResourceAsStream()
ClassLoader
as Thread.currentThread().getContextClassLoader()
webapps中的另一种替代方法是ServletContext#getResource()和ServletContext#getResourceAsStream()。它能够访问位于webwebapp项目的/WEB-INF公用文件夹中的文件,包括该文件夹。该ServletContext是由继承的Servlet可用getServletContext()的方法,你可以把它原样。
ServletContext#getResource()
ServletContext#getResourceAsStream()
ServletContext
getServletContext()