当前位置: 首页 > 知识库问答 >
问题:

为什么要使用java。lang.ClassLoader。jar内资源的getResource

池赞
2023-03-14

使用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想法来看,它运行得很好,但在部署到Tomcat服务器后,我遇到了这样的异常:

java.io.FileNotFoundException: File'file:/usr/local/tomcat/webapps/prod-lims/WEB-INF/lib/abc-1.2-SNAPSHOT. jar! com/domain/example/抱歉/机密/little_text.txt'不存在

之后,我在SO和其他我需要使用ClassLoader的网站上找到了很多答案。getResourceAsStream()或类。JAR内资源的getResourceAsStream()方法。当然,我试图以旧式的方式重新设计我的代码,瞧现在可以工作了:

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中的资源?我很好奇,因为超级服务。getClass()。getClassLoader()。getResource(“com/domain/example/sorry/confidential/little\u text.txt”)返回非null,但构造的文件具有canRead()==false和isExist()==false。


共有1个答案

蓬兴国
2023-03-14

File、FileInputStream、FileUtils等用于访问文件系统,而从文件系统的角度来看,嵌入到JAR中的“文件”实际上不是文件。因此,您只能通过实际上打算从归档文件中读取的工具来访问这些嵌入的文件(基本上,JAR只是一个奇特的ZIP)。

顺便提一下,Java中的File对象为非null并不意味着该文件实际存在。你可以做得很好:

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

并且文件将为非null(但isReadable()isExist()应为false)。这与你的资源行为相同。

它很可能在IDE中工作,因为该文件在您的工作区中确实以非归档文件的形式存在。

 类似资料:
  • 问题内容: 大多数情况下,我看到的finally块仅用于 我的问题是,如果f的范围以封闭块结尾,为什么我们需要在finally中将其关闭? 问题答案: 因为垃圾回收与资源清理 不是 一回事。 例如,如果您有一个超出范围的JDBC连接对象,则没有信号发送到数据库服务器以指示不再需要打开的游标和连接。没有这些消息,您最终将耗尽可用的游标和连接数。 与文件句柄和任何其他资源相同。自己清理后。

  • 问题内容: 在托管bean中,是在常规Java对象构造函数之后调用的。 为什么要使用初始化而不是常规构造函数本身? 问题答案: 因为在调用构造函数时,bean尚未初始化-即没有注入依赖项。在该@PostConstruct方法中,bean已完全初始化,你可以使用依赖项。 因为这是保证可以在bean生命周期中仅调用一次此方法的协定。可能会发生(尽管不太可能)容器在其内部工作中多次实例化bean,但它保

  • 问题内容: 谁能帮助解释为什么JNDI应该是公开数据库/ jms等服务的首选方式? 我遇到的所有帖子都谈到了不必加载特定的驱动程序管理器,从连接池中受益等优点,但是可以通过在属性文件中指定驱动程序管理器并使用反射来轻松实现。 连接池也可以通过将正确的实现方式通过spring或其他方式连接到应用Bean中来实现。 那么,为什么使用JNDI会更好呢? 问题答案: 当您必须在不同环境之间移动应用程序时,

  • 问题内容: 我想使用jar文件中的java代码播放.wav文件作为资源。我的代码看起来像这样- 我的jar文件之一中存在WindowsNavigationStart.wav文件。但是得到以下异常- 请给我一个解决方案。谢谢你们。 问题答案: 更改: 至:

  • 问题内容: 通过阅读文档,我确切地了解getattr()和setattr()的作用。但它也明确表示等同于和等同于。 那我为什么要使用它们? 问题答案: 因为您也可以使用动态变量: 您不能使用常规属性访问语法来做到这一点。 请注意,如果 缺少 属性,还需要返回一个可选的默认值: 使用您可以从其他名称(而不是文字)中提取属性名称: 或者您可以用来设置动态属性:

  • 我有一个企业应用程序,我正在从Ant构建转换为Maven。它几乎完全转化了;这是我最不需要解决的问题。该应用程序打包为一个EAR文件,其中包含两个WAR,并具有一个JAR模块,该模块提供了应用程序的所有核心功能。 我正在使用Freemarker模板库为应用程序发送的自动电子邮件生成消息体。Freemarker需要它的*。ftl模板文件要放在类路径上,因为这是核心应用程序功能,不是特定于一场战争或另