getResourceAsStream() vs FileInputStream

我试图在Web应用程序中加载文件,当我使用时遇到异常。但是,使用相同的路径,当我这样做时,我能够加载文件。这两种方法之间有什么区别,为什么一种方法有效,而另一种方法不起作用?FileNotFoundFileInputStreamgetResourceAsStream()


答案 1

java.io.File 和 consorts 作用于本地磁盘文件系统。问题的根本原因是 中的相对路径依赖于当前工作目录。即启动JVM的目录(在你的例子中:Web服务器的目录)。例如,这可能是或完全不同的东西,但因此不是或你所期望的任何东西。在正常的 Eclipse 项目中,这将是 .您可以通过以下方式了解当前工作目录:java.ioC:\Tomcat\binC:\Tomcat\webapps\contextnameC:\Eclipse\workspace\projectname

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

但是,工作目录在编程上是不可控的。您应该更喜欢在 API 中使用绝对路径而不是相对路径。例如.FileC:\full\path\to\file.ext

您不想硬编码或猜测Java(Web)应用程序中的绝对路径。这只是可移植性问题(即它在系统X中运行,但不在系统Y中运行)。通常的做法是将这些类型的资源放在类路径中,或者将其完整路径添加到类路径中(在 Eclipse 等 IDE 中,分别是文件夹和“构建路径”)。通过这种方式,你可以借助 ClassLoader#getResource() 或 ClassLoader#getResourceAsStream() 来获取它们。它能够相对于类路径的“根”找到文件,正如您巧合所发现的那样。在 Web 应用程序(或任何其他使用多个类加载器的应用程序)中,建议使用 as 返回的 ,以便您也可以查看 web 应用程序上下文的“外部”。srcClassLoaderClassLoaderThread.currentThread().getContextClassLoader()

webapps中的另一种选择是ServletContext#getResource()及其对应的ServletContext#getResourceAsStream()。)。它能够访问位于 webapp 项目公用文件夹中的文件,包括该文件夹。在 servlet 中可以通过继承的 getServletContext() 方法获得,您可以按原样调用它。web/WEB-INFServletContext

另请参阅:


答案 2

getResourceAsStream是用于Web应用程序的正确方法(正如您已经了解的那样)。

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


推荐