【问题标题】:Why to use java.lang.ClassLoader.getResource for resource within jar为什么使用 java.lang.ClassLoader.getResource 作为 jar 中的资源
【发布时间】:2020-06-19 18:00:19
【问题描述】:

使用 Java 8、Tomcat 8+。

我遇到过这样的问题 - 我正在尝试读取 lib 中 jar 中的 txt 资源。我使用了以下代码:

import java.io.File;
import org.apache.commons.io.FileUtils;

// ....    
// code within some class method
File file = new File(superService.getClass().getClassLoader()
                    .getResource("com/domain/example/sorry/confidential/little_text.txt")
                    .getFile())
return FileUtils.readFileToString(file, "UTF-8")

虽然它在我的 Intellij IDEA 上运行良好,但在 Tomcat 服务器上部署后我得到了这样的异常:

java.io.FileNotFoundException: 文件 ‘文件:/usr/local/tomcat/webapps/prod-lims/WEB-INF/lib/abc-1.2-SNAPSHOT.jar!com/domain/example/sorry/confidential/little_text.txt’ 不存在

之后,我在 SO 和其他网站中找到了很多答案,我需要使用 ClassLoader.getResourceAsStream() 或 Class.getResourceAsStream() 方法来获取 JAR 中的资源。当然,我尝试以旧式方式重新设计我的代码 - 瞧! - 现在可以使用了:

import java.io.BufferedReader;
import java.io.InputStreamReader;

// ....    
// code within some class method
InputStream inputStream = superService.getClass().getClassLoader()
               .getResourceAsStream("com/domain/example/sorry/confidential/little_text.txt")


StringBuilder resultStringBuilder = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream))
    try {
        String line;
        while ((line = br.readLine()) != null) {
            resultStringBuilder.append(line).append("\n");
        }
        } catch(Exception e) {
        //just a formal catch - don't mind for now
    }

return resultStringBuilder.toString()

好的,我对这个可行的解决方案很满意。但是我在任何地方都找不到任何明确的解释:为什么 getResourceAsStream 有效,同时“文件”方法不适用于 JAR 中的资源?我很好奇,因为superService.getClass().getClassLoader().getResource("com/domain/example/sorry/confidential/little_text.txt") 返回不为空,但构造的文件有canRead() == falseisExist() == false

【问题讨论】:

    标签: java classloader


    【解决方案1】:

    File、FileInputStream、FileUtils 等旨在访问文件系统,从文件系统的角度来看,嵌入 JAR 中的“文件”实际上并不是文件。因此,您只能通过实际上打算从存档内部读取的工具访问这些嵌入文件(基本上,JAR 只是一个花哨的 ZIP)。

    顺便说一句,Java 中的 File 对象是非空的这一事实并不意味着该文件确实存在。你可以这样做:

    File file = new File("I:\\do\\not.exist");
    

    file 将是非空的(但isReadable()isExist() 应该是假的)。这与您为资源获得的行为相同。

    它可能在 IDE 中工作,因为文件确实实际上作为非归档文件存在于您的工作区中。

    【讨论】:

    猜你喜欢
    • 2019-02-04
    • 2011-05-13
    • 1970-01-01
    • 2012-04-27
    • 1970-01-01
    • 2012-06-18
    • 1970-01-01
    • 2012-01-15
    • 1970-01-01
    相关资源
    最近更新 更多