我试着在一个网络应用程序中加载一个文件,我得到了一个 FileNotFound 当我使用 FileInputStream . 但是,使用相同的路径,我可以加载文件时,我这样做了 getResourceAsStream() . 这两种方法有什么区别,为什么一种有效而另一种无效?
FileNotFound
FileInputStream
getResourceAsStream()
bwleehnv1#
这个 java.io.File 和consorts作用于本地磁盘文件系统。问题的根本原因是 java.io 依赖于当前工作目录。i、 e.启动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
C:\Eclipse\workspace\projectname
System.out.println(new File(".").getAbsolutePath());
但是,工作目录绝不是可编程控制的。您应该更喜欢在中使用绝对路径 File api而不是相对路径。例如 C:\full\path\to\file.ext .您不想硬编码或猜测java(web)应用程序中的绝对路径。这是唯一的可移植性问题(即它在systemx中运行,但在systemy中不运行)。通常的做法是将这些资源放在类路径中,或者将其完整路径添加到类路径中(在像eclipse这样的ide中,这是 src 文件夹和“构建路径”。这样,你就可以抓住他们的帮助下 ClassLoader 由 ClassLoader#getResource() 或者 ClassLoader#getResourceAsStream() . 它能够相对于类路径的“根”定位文件,正如您碰巧发现的那样。在webapplications(或任何其他使用多个类加载器的应用程序)中,建议使用 ClassLoader 由返回 Thread.currentThread().getContextClassLoader() 因此,您也可以查看“外部”webapp上下文。webapps的另一个选择是 ServletContext#getResource() 以及它的对应物 ServletContext#getResourceAsStream() . 它能够访问位于公共区域的文件 web webapp项目的文件夹,包括 /WEB-INF 文件夹。这个 ServletContext 在servlet中由继承的 getServletContext() 方法,可以按原样调用它。
File
C:\full\path\to\file.ext
src
ClassLoader
ClassLoader#getResource()
ClassLoader#getResourceAsStream()
Thread.currentThread().getContextClassLoader()
ServletContext#getResource()
ServletContext#getResourceAsStream()
web
/WEB-INF
ServletContext
getServletContext()
在基于servlet的应用程序中,在何处放置配置资源文件以及如何读取配置资源文件?servletcontext.getrealpath(“/”)是什么意思?我应该在什么时候使用它在servlet应用程序中保存上载文件的推荐方法如何在基于servlet的web应用程序中临时保存生成的文件
pw136qt22#
getResourceAsStream 对于web应用程序来说,这是正确的方法(正如您已经学到的)。原因是,如果你在战争中打包你的web应用程序,那么从文件系统读取数据就无法工作。这是打包web应用程序的正确方法。这种方式是可移植的,因为您不依赖于绝对文件路径或安装应用服务器的位置。
getResourceAsStream
yr9zkbsy3#
fileinputstream将从java进程的工作目录中加载一个文件路径,该路径作为相对路径传递给构造函数。通常在web容器中,这类似于 bin 文件夹。 getResourceAsStream() 将从应用程序的类路径加载相对的文件路径。
bin
bxjv4tth4#
这个 FileInputStream 类直接与底层文件系统一起工作。如果有问题的文件实际不在那里,它将无法打开它。这个 getResourceAsStream() 方法的工作原理不同。它尝试使用 ClassLoader 它被召唤的班级。这使得它能够找到,例如,嵌入到 jar 文件夹。
jar
cwdobuhd5#
getresourceasstream()通过classname的类加载器加载文件。如果类来自jar文件,则资源将从该文件加载。fileinputstream用于从文件系统读取文件。
rseugnpd6#
我在这里通过将它们标记为文件读取(java.io)和资源读取(classloader.getresourceasstream())来区分这两种用法。文件读取-1。在本地文件系统上工作。2.尝试将从当前jvm启动目录请求的文件定位为根3。理想情况下,使用文件在预先确定的位置(如/dev/files或c:\data)进行处理时效果良好。资源读取-1。在类路径2上工作。尝试在当前或父类加载器类路径中定位文件/资源。3.在尝试从打包文件(如war或jar)加载文件时非常理想。
6条答案
按热度按时间bwleehnv1#
这个
java.io.File
和consorts作用于本地磁盘文件系统。问题的根本原因是java.io
依赖于当前工作目录。i、 e.启动jvm的目录(在您的例子中:web服务器的目录)。例如,这可能是C:\Tomcat\bin
或者完全不同的东西,但不是这样C:\Tomcat\webapps\contextname
或者不管你想怎样。在一个普通的eclipse项目中,这将是C:\Eclipse\workspace\projectname
. 您可以通过以下方式了解当前工作目录:但是,工作目录绝不是可编程控制的。您应该更喜欢在中使用绝对路径
File
api而不是相对路径。例如C:\full\path\to\file.ext
.您不想硬编码或猜测java(web)应用程序中的绝对路径。这是唯一的可移植性问题(即它在systemx中运行,但在systemy中不运行)。通常的做法是将这些资源放在类路径中,或者将其完整路径添加到类路径中(在像eclipse这样的ide中,这是
src
文件夹和“构建路径”。这样,你就可以抓住他们的帮助下ClassLoader
由ClassLoader#getResource()
或者ClassLoader#getResourceAsStream()
. 它能够相对于类路径的“根”定位文件,正如您碰巧发现的那样。在webapplications(或任何其他使用多个类加载器的应用程序)中,建议使用ClassLoader
由返回Thread.currentThread().getContextClassLoader()
因此,您也可以查看“外部”webapp上下文。webapps的另一个选择是
ServletContext#getResource()
以及它的对应物ServletContext#getResourceAsStream()
. 它能够访问位于公共区域的文件web
webapp项目的文件夹,包括/WEB-INF
文件夹。这个ServletContext
在servlet中由继承的getServletContext()
方法,可以按原样调用它。另请参见:
在基于servlet的应用程序中,在何处放置配置资源文件以及如何读取配置资源文件?
servletcontext.getrealpath(“/”)是什么意思?我应该在什么时候使用它
在servlet应用程序中保存上载文件的推荐方法
如何在基于servlet的web应用程序中临时保存生成的文件
pw136qt22#
getResourceAsStream
对于web应用程序来说,这是正确的方法(正如您已经学到的)。原因是,如果你在战争中打包你的web应用程序,那么从文件系统读取数据就无法工作。这是打包web应用程序的正确方法。这种方式是可移植的,因为您不依赖于绝对文件路径或安装应用服务器的位置。
yr9zkbsy3#
fileinputstream将从java进程的工作目录中加载一个文件路径,该路径作为相对路径传递给构造函数。通常在web容器中,这类似于
bin
文件夹。getResourceAsStream()
将从应用程序的类路径加载相对的文件路径。bxjv4tth4#
这个
FileInputStream
类直接与底层文件系统一起工作。如果有问题的文件实际不在那里,它将无法打开它。这个getResourceAsStream()
方法的工作原理不同。它尝试使用ClassLoader
它被召唤的班级。这使得它能够找到,例如,嵌入到jar
文件夹。cwdobuhd5#
getresourceasstream()通过classname的类加载器加载文件。如果类来自jar文件,则资源将从该文件加载。
fileinputstream用于从文件系统读取文件。
rseugnpd6#
我在这里通过将它们标记为文件读取(java.io)和资源读取(classloader.getresourceasstream())来区分这两种用法。
文件读取-1。在本地文件系统上工作。2.尝试将从当前jvm启动目录请求的文件定位为根3。理想情况下,使用文件在预先确定的位置(如/dev/files或c:\data)进行处理时效果良好。
资源读取-1。在类路径2上工作。尝试在当前或父类加载器类路径中定位文件/资源。3.在尝试从打包文件(如war或jar)加载文件时非常理想。