Java 读取resources下的资源文件

2023-11-19

Web项目中应该经常有这样的需求,在maven项目的resources目录下放一些文件。比如一些配置文件,资源文件等。文件的读取方式有好几种方式,本文会对常用的读取方式做一个总结,并说明一下应该注意的地方。

准备工作

  • 新建一个spring-test 的maven项目,resources目录下创建测试文件conf.properties、city_code.json (json文件夹下)。

  • 添加pom依赖

使用 FileUtils、IOUtils等工具类,需要引入 commons-io jar包。

<!-- spring web -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.2.7.RELEASE</version>
</dependency>

<!-- commons-io -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>

一、通过ClassLoader读取文件

ClassLoader.getResourceAsStream()获取文件输入流

public void loadPropertiesFile() throws IOException {
    Properties properties = new Properties();
    properties.load(this.getClass().getClassLoader().getResourceAsStream("conf.properties"));
    log.info(properties.getProperty("file.max.size"));
}

ClassLoader.getResourceAsStream()获取文件的URL

public void loadJsonFile() throws IOException {
    //获取文件的URL
    URL url = this.getClass().getClassLoader().getResource("json/city_code.json");
    String content = FileUtils.readFileToString(new File(url.getPath()), StandardCharsets.UTF_8);
    log.info(content);
}

二、通过Class读取文件

Class.getResourceAsStream()获取文件的输入流

public void loadPropertiesFile() throws IOException {
    Properties properties = new Properties();
    properties.load(this.getClass().getResourceAsStream("/conf.properties"));
    log.info(properties.getProperty("file.max.size"));
}

Class.getResourceAsStream()获取文件的URL

public void loadJsonFile() throws IOException {
    //获取文件的URL
    URL url = this.getClass().getResource("/json/city_code.json");
    String content = FileUtils.readFileToString(new File(url.getPath()), StandardCharsets.UTF_8);
    log.info(content);
}
Class.getResourceAsStream() 和 ClassLoader.getResourceAsStream()有一个显著的区别,那就是前者加载的时候需要在文件路径前加一个 "/"。

三、Spring项目读取文件

  • 通过ResourceUtils.getFile()方法可以读取File
public void loadJsonFile() throws IOException {
    //获取文件的URL
    File file = ResourceUtils.getFile("classpath:json/city_code.json");
    String content = FileUtils.readFileToString(file, StandardCharsets.UTF_8);
    log.info(content);
}
  • 通过ClassPathResource获取输入流
ClassPathResource的构造参数path不会做绝对路径的区分,"json/city_code.json" 或者 "/json/city_code.json"都能成功获取文件的输入流。
@SneakyThrows
public void loadJsonFil1(){
    ClassPathResource classPathResource = new ClassPathResource("json/city_code.json");
    InputStream inputStream = classPathResource.getInputStream();
    String content = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
    log.info(content);
}

四、如何区分要不要加"/"

在使用这些方式读取文件时,都需要传入一个文件路径。至于要不要在路径前加一个"/"时常让人感到很困惑,这里稍微做一个总结。如果通过Class来读取文件,那么路径需要以"/"开始。通过ClassLoader或者Spring提供的工具类读取文件其实都不需要在路径前加"/"。

五、总结

碰到这些问题最好的解决办法,就是去翻一翻源码,然后断点调试看看一个读取文件过程中各个变量的值。通过看源码的方式不但能解决问题,还能帮自己捋清楚这些读取文件方式到底有什么联系和区别。

这里摘一段Class类两个方法的源码,通过代码可以得到如下结论。

  • Class和ClassLoader都可以读取文件,不过Class读取文件还是通过ClassLoader来实现的。
  • Class读取文件之前需要经过resolveName方法,resolveName会对文件路径进行解析。如果路径以"/"开始,则删除"/"。如果路径不是"/"开始,则会在文件路径前拼接包名前缀,然后用新的文件路径来读取文件。
public java.net.URL getResource(String name) {
    name = resolveName(name);
    ClassLoader cl = getClassLoader0();
    if (cl==null) {
        // A system class.
        return ClassLoader.getSystemResource(name);
    }
    return cl.getResource(name);
}
public InputStream getResourceAsStream(String name) {
    name = resolveName(name);
    ClassLoader cl = getClassLoader0();
    if (cl==null) {
        // A system class.
        return ClassLoader.getSystemResourceAsStream(name);
    }
    return cl.getResourceAsStream(name);
}
/**
 * Add a package name prefix if the name is not absolute Remove leading "/"
 * if name is absolute
 */
private String resolveName(String name) {
    if (name == null) {
        return name;
    }
    if (!name.startsWith("/")) {
        Class<?> c = this;
        while (c.isArray()) {
            c = c.getComponentType();
        }
        String baseName = c.getName();
        int index = baseName.lastIndexOf('.');
        if (index != -1) {
            name = baseName.substring(0, index).replace('.', '/')
                +"/"+name;
        }
    } else {
        name = name.substring(1);
    }
    return name;
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java 读取resources下的资源文件 的相关文章

  • Java - 了解 PrintWriter 和刷新的需要

    好吧 首先我对所有代码表示歉意 但我觉得代码太多总比代码不够好 我正在制作一个简单的聊天客户端和印刷机 尤其是我正在努力解决的问题 使用现在的代码 它将与服务器类交互 并且完美地打印我想要打印的内容 但是 当我删除 writer flush
  • 从 Java 启动外部进程:stdout 和 stderr

    我正在使用标准从 java 启动一个外部进程java lang Process 我试图弄清楚该过程的输出是什么 但是采用结合了两者的格式stdout and stderr 目前 我有Process getInputStream它提供了访问s
  • 平衡括号问题的优化解

    给定一个仅包含字符的字符串 and 判断输入字符串是否有效 输入字符串在以下情况下有效 左括号必须由相同类型的括号封闭 左括号必须按正确的顺序关闭 请注意 空字符串也被视为有效 示例1 Input Output true Example 2
  • 从另一个类添加 Swing 组件

    我正在学习java 我正在尝试从另一个类向我的框架添加一个菜单栏 练习将代码划分为多个类以更好地组织程序 这是我的代码示例 public class MainApp public static void main String args C
  • shell解析json并循环输出组合变量

    杰斯克喜欢我之前的话题 https stackoverflow com questions 74063588 shell parsing json contains spaces in string 我知道如何解析带有空格的简单 json
  • 解析包含 json 字符串的 json

    我有一个 json 里面有另一个 json 但它在双引号内 因此它给了我一个解析错误 除了使用之外还有什么方法可以解析这个jsongsub替换双引号 obj Name FirstName Douglas LastName Crockford
  • Android Google 地图:隐藏整个地图的多边形或形状

    我试图隐藏除一个区域之外的整个地图 因为我使用的多边形在我想要显示的区域中有一个洞 问题在于 根据缩放的不同 空白区域会被多边形的颜色覆盖 或者多边形会失去其颜色 这是代码 polygon hide all world map float
  • 如何将带有自定义标头的任意 JSON 数据发送到 REST 服务器?

    TL DR 如何将 JSON 字符串发送到带有 auth 标头的 REST 主机 我尝试了 3 种不同的方法 发现一种适用于匿名类型 为什么我不能使用匿名类型 我需要设置一个名为 Group Name 的变量 并且连字符不是有效的 C 标识
  • 在 Java/GWT 中解析用户时间输入

    解析用户在 GWT 中的文本字段中键入的时间的最佳方法是什么 默认时间格式要求用户完全按照区域设置指定的时间格式输入时间 我想要更加灵活 因为用户可以通过多种不同的方式输入时间 例如 8 8p 8pm 8 15pm 13 15 1315 1
  • 如何在Android中使用资源

    一个人如何使用资产 我有这个代码 AssetManager assets getAssets InputStream stream assets open test txt 看起来它只能在 Activity 类中使 用 如果我尝试在另一个类
  • 为什么 Cassandra 客户端在生产中没有 epoll 时会失败? [复制]

    这个问题在这里已经有答案了 当我在本地运行服务时 我收到一条警告 指出 epoll 不可用 因此它使用 NIO 很公平 当我将其部署到 Kubernetes 中时 我得到了以下信息 这导致服务无法运行 2017 03 29T19 09 22
  • 使用 Lint 和 SonarQube 分析 Android 项目

    我真的 溢出 了试图让这些东西一起工作 我按照这里的指示进行操作 http docs sonarqube org display PLUG Android Lint Plugin http docs sonarqube org displa
  • JavaFX 8 默认消息图标

    随着 JavaFX 的最近几次更新 我们收到了警报 我想获取消息的默认图标 错误 警告 在Swing中 我可以通过一些方式获取L F消息图标UIManager的属性 如何在 JavaFX 中获取消息的默认图标 它们是包含在属性中 还是由 C
  • JavaScript fetch API - 为什么response.json()返回一个promise对象(而不是JSON)? [复制]

    这个问题在这里已经有答案了 我刚刚开始学习 Fetch API https developer mozilla org en US docs Web API Fetch API Using Fetch https developer moz
  • 为什么我的 Java 路径中添加了“L”?

    我在我的类路径中加载了一个 jar 在 iReport 中 如果重要的话 我确信它具有所需的方法 但是当我尝试测试连接 从而调用该 jar 时 我得到一个 java lang NoSuchMethodError 说它正在引用班上 Lorg
  • PagedList 的 Newtonsoft.Json 序列化不包含某些属性

    我正在尝试序列化 PagedList 对象 https github com martijnboland MvcPaging blob master src MvcPaging PagedList cs https github com m
  • 使用 OpenNLP 获取句子的解析树。陷入困境。

    OpenNLP 是一个关于自然语言处理的 Apache 项目 NLP 程序的目标之一是解析一个句子 并给出其语法结构的树 例如 天空是蓝色的 这句话 可能会被解析为 S NP VP The sky is blue where S是句子 NP
  • Java分数计算器

    我对 Java 编程还很陌生 我的 AP 计算机编程课程有作业要完成 所以请耐心等待 我必须弄清楚如何将两个分数相乘 我想知道是否有任何方法可以在方法内部声明变量并在该方法外部使用它 我在介绍方法中的 while 循环 谢谢您 希望这不会令
  • 丰富:数据表行跨度问题

    我需要创建一个 rich dataTable 甚至扩展 具有以下功能 我有一个公司类 其中包含产品对象的集合 我想展示下表 我仍然没有弄清楚如何使用子表执行此操作 在所有示例中 我发现子表具有与主表完全相同的列 据推测 我需要在前两列中使用
  • 是什么让热部署成为“难题”?

    在工作中 我们经常遇到这样的问题 永久代内存不足 http www jroller com agileanswers entry preventing java s java lang例外 团队负责人认为这是 JVM 中的一个错误 与代码的

随机推荐

  • SpringMvc Controller中几种参数的绑定

    1 SpringMVC默认支持的绑定类型有 2 HttpServletRequest对象 通过request对象可以获取参数信息 3 HttpServletResponse对象 通过response对象可以处理响应信息 4 HttpSess
  • 计算机系统课程 笔记总结 CSAPP第四章 处理器体系结构(4.1-4.3)

    GitHub计算机系统CSAPP课程资源 计算机系统课程 笔记总结 CSAPP第二章 信息的表示和处理 2 1 2 2 计算机系统课程 笔记总结 CSAPP第二章 信息的表示和处理 2 3 2 4 计算机系统课程 笔记总结 CSAPP第三章
  • ChatGPT办公应用:制作PPT大纲

    正文共 617字 阅读大约需要 4 分钟 解决方案专家必备技巧 您将在4分钟后获得以下超能力 制作PPT大纲 Beezy评级 B级 经过简单的寻找 大部分人能立刻掌握 主要节省时间 推荐人 Kim 编辑者 Yuke PPT技能是一项重要办公
  • PID算法理论,运用,代码编写详解

    什么是PID 我相信能来看这篇文章的应该都知道什么是PID PID就是一种控制算法 利用比例运算 P 积分运算 I 和微分运算 D 一起控制某一事件 当然也可以只运用其中一个也可以两两结合 运用举例 比如我们家里都会有的那个电热水器 有点热
  • msvcp140.dll丢失的4种解决方法,快速修复msvcp140.dll文件

    msvcp140 dll丢失在所有的dll文件丢失里面 也算是经常丢失的老油条了 我们应该对它都不陌生吧 不过直到今天都还有人不知道怎么修复msvcp140 dll文件 小编觉得非常有必要来给大家详细的说说吧 聊一下msvcp140 dll
  • android获取缓存大小并清理缓存

    本文主要注重介绍实战操作 理论知识可能介绍的不多 勿喷 简单说两句缓存的好处 采用缓存 可以进一步大大缓解数据交互的压力 又能提供一定的离线浏览 下边我简略列举一下缓存管理的适用环境 1 提供网络服务的应用 2 数据更新不需要实时更新 哪怕
  • 数学建模的LINGO基础

    LINGO是Linear Interactive and General Optimizer的缩写 即 交互式的线性和通用优化求解器 由美国LINDO系统公司 Lindo System Inc 推出的 可以用于求解非线性规划 也可以用于一些
  • Operator ‘

    如何解决Operator cannot be applied to java lang String java lang String 或者Operator cannot be applied to java lang String jav
  • springboot集成eureka

    分为3个项目来讲解 注册中心 provider consumer 注册中心 注册中心pom xml添加
  • 什么是模式、什么是模式识别、模式识别的方法、过程

    什么是模式 pattern 模式是存在于时间和空间中可观察的物体 如果可以区分相同或者相似的物体类别 可区分的物体称之为模式 模式不是指具体的物体 而是抽象的类别 例如 人这个类别是一种模式 自行车这个类别是一种模式 什么是模式识别 1 模
  • 用Python爬取英雄联盟(lol)全部皮肤

    小三 怎么了小二 一副无精打采的样子 小二 唉 别提了 还不是最近又接触了一个叫英雄联盟的游戏 游戏中很多皮肤都需要花钱买 但是我钱不够呀 小三 咋得 钱攒够了你还要买呀 还吃不吃饭了 要我说 你干脆将英雄的炫彩皮肤都爬下来欣赏一下得了 饭
  • 预警:传统的QA岗位将被DevOps淘汰

    导读 在大多数机构或公司里 软件开发过程主要遵循一个或多个开发模型 例如瀑布模型或敏捷模型 在瀑布模型中 测试活动一般都在后期进行 软件开发完成后 缺陷被QA团队找出 然后再被修复 后两个活动不断循环和重复 指导管理者认为软件可以被公开发布
  • 在wsl中判断wsl的版本是wsl1还是wsl2

    判断wsl的版本 代码逻辑 通过判断 cat proc version 是否包含wsl等字符来判断wsl的版本 代码 bin bash Get the content of proc version proc version cat pro
  • chatgpt赋能python:如何用Python进行SEO优化

    如何用Python进行SEO优化 介绍 Search Engine Optimization SEO 即搜索引擎优化 是提高网站排名和流量的关键 Python作为一种强大的编程语言 可以帮助我们优化网站的SEO 在本文中 我们将探讨如何用P
  • 如何批量Ping 1000个IP地址,一个小技巧节约N小时?

    一 批量ping网段 对于一个网段ip地址众多 如果单个检测实在麻烦 那么我们可以直接批量ping网段检测 那个ip地址出了问题 一目了然 先看代码 直接在命令行窗口输入 for L D in 1 1 255 do ping 10 168
  • 定义类数组

    编写学生类 包含姓名 学号 成绩三个属性 题目要求 1 为学生类添加构造函数给每个成员属性赋值 使用this关键字 2 为学生添加toString 方法显示所有属性 3 在测试类中定义学生数组 长度为4 分别给数组每个元素赋值 然后循环调用
  • Vue自定义插件的编写

    如何实现一个vue的自定义插件 div div
  • windows 如何查询主板sn(主板ID)

    wmic bios get serialnumber
  • dell服务器维护软件,Dell服务器硬件,RAID等查询和维护软件OMSA_推荐

    Dell服务器硬件 RAID等查询和维护软件OMSA 推荐 原创 chenshengang2014 01 17 19 07 03 著作权 阅读数 441 著作权归作者所有 来自51CTO博客作者chenshengang的原创作品 如需转载
  • Java 读取resources下的资源文件

    Web项目中应该经常有这样的需求 在maven项目的resources目录下放一些文件 比如一些配置文件 资源文件等 文件的读取方式有好几种方式 本文会对常用的读取方式做一个总结 并说明一下应该注意的地方 准备工作 新建一个spring t