读取打包到JAR中的文件:常见问题与解决方案(文件在但是报错not find)

读取打包到JAR中的文件:常见问题与解决方案

在这里插入图片描述

喝淡酒的时候,宜读李清照;喝甜酒时,宜读柳永;喝烈酒则大歌东坡词。其他如辛弃疾,应饮高梁小口;读放翁,应大口喝大曲;读李后主,要用马祖老酒煮姜汁到出怨苦味时最好;至于陶渊明、李太白则浓淡皆宜,狂饮细品皆可。
—— 林清玄 《温一壶月光下酒》

在Java应用中,特别是在使用Spring框架时,常常需要从JAR文件中读取资源。这个操作在开发期间看起来很简单,因为文件系统直接可访问。然而,一旦应用被打包成JAR后运行,常见的文件访问方法就会失败,因为JAR文件内的资源不能像普通文件那样被直接访问。
在Java和Spring框架中,理解资源文件的正确处理尤为重要,尤其是当资源文件被包含在JAR包内时。下面,我们将分析一个常见的错误示例,以及如何通过更合适的方法来纠正这个问题。

错误的案例:直接使用File API读取Spring的注入资源

在使用Spring框架时,我们可能会尝试直接将使用@Value注解注入的Resource转换为File来处理。这在资源文件位于文件系统中时有效,但如果这些资源位于JAR包内,此方法将导致失败。

示例错误代码:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;

@Component
public class ResourceReader {
    
    @Value("classpath:assets/document-formats/onlyoffice-docs-formats.json")
    private Resource resourceFile;

    public void readFile() {
        try {
            File file = resourceFile.getFile();  // 这里会抛出IOException
            // 进一步处理文件...
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("Failed to access resource file", e);
        }
    }
}
错误原因:

在这里插入图片描述

在上述代码中,Resource.getFile()方法在资源文件位于JAR包内时会失败,因为JAR内的资源并不是一个真正的磁盘上的文件,而是JAR文件的一部分。因此,尝试获取其作为File对象会抛出IOException

常见问题说明

当将应用打包成JAR(Java ARchive)文件时,所有的类文件和资源文件都被封装在一个单一的文件中。许多开发者习惯使用类似于文件路径的方式来访问资源,如使用File类。这在开发阶段没有问题,因为资源文件直接位于文件系统上。但是,一旦资源被封装到JAR中,尝试以同样的方式访问这些资源会导致FileNotFoundExceptionNullPointerException,因为File类不能读取JAR内部的路径。

解决方案
1. 使用Class.getResourceAsStream()方法

Java提供了Class.getResourceAsStream(String path)方法,它能够从当前类的类路径中读取资源为InputStream。这个方法适用于任何形式的类路径资源,包括JAR文件内的资源。

InputStream is = MyClass.class.getResourceAsStream("/path/to/your/resource.txt");
if (is != null) {
    try (BufferedReader reader = new BufferedReader(new InputStreamReader(is))) {
        reader.lines().forEach(System.out::println);
    } catch (IOException e) {
        e.printStackTrace();
    }
} else {
    System.out.println("Resource not found");
}
2. 使用ClassLoader.getResourceAsStream()方法

Class.getResourceAsStream()类似,ClassLoader.getResourceAsStream()也提供了一种从类加载器的类路径中读取资源的方法。这个方法不需要从类的角度去定位资源,而是直接从类路径的根开始。

InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("path/to/your/resource.txt");
if (is != null) {
    try (BufferedReader reader = new BufferedReader(new InputStreamReader(is))) {
        reader.lines().forEach(System.out::println);
    } catch (IOException e) {
        e.printStackTrace();
    }
} else {
    System.out.println("Resource not found");
}
3. 使用Spring框架的Resource抽象

如果你在使用Spring框架,Spring提供了一个非常强大的资源抽象,通过Resource接口来统一处理资源。Spring可以通过ApplicationContext来访问资源,使用Resource接口可以非常灵活地处理各种资源类型。

@Autowired
private ResourceLoader resourceLoader;

public void readResource() {
    Resource resource = resourceLoader.getResource("classpath:path/to/your/resource.txt");
    try (InputStream is = resource.getInputStream()) {
        new BufferedReader(new InputStreamReader(is))
            .lines()
            .forEach(System.out::println);
    } catch (IOException e) {
        e.printStackTrace();
    }
}
最佳实践
  • 使用流处理资源:无论资源位于文件系统还是JAR文件中,始终使用InputStream来访问资源。这样可以确保应用的可移植性和灵活性。
  • 优先使用Spring的Resource抽象:如果你使用Spring框架,利用Spring的Resource抽象来处理资源,这样可以更容易地集成更多Spring功能。
  • 错误处理:总是进行适当的错误处理,如资源不存在时的处理。这可以避免运行时错误并且精确定位错误点。

破问题太坑了——

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/597115.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python数据清洗与可视化实践:国际旅游收入数据分析

文章目录 概要整体流程名词解释NumPyPandasMatplotlibre 技术细节数据清洗可视化 小结 概要 在本篇博客中,我们将通过一个实际的案例,演示如何使用Python进行数据清洗和可视化,以分析国际旅游收入数据。我们将使用Python中的Pandas库来进行数…

04-25 周四 FastBuild重构实践-TLS、全局捕获异常、一键配置

04-25 周四 FastBuild重构实践 时间版本修改人描述04-25V0.1宋全恒新建文档2024年5月6日14:33:16V1.0宋全恒完成文档撰写 简介 由于 04-22 周日 阿里云-瑶光上部署FastBuild过程(配置TLS、自定义辅助命令)描述了重新部署一个FastBuild实例的过程,通过阅读这个&…

线性表的概念与结构,以及顺序表和链表的简单概念

1.线性表 线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串... 线性表在逻辑上是线性结构,也就说是连续的一条直线…

JS hook cookie

JS hook cookie cookie 的值是V,v是动态变化的 可以看到D中生成了cookie的值n 尝试使用RPC定位到cookie。 替换内容,下断点。 将写好的RPC代码直接插入 加入代码,file.virjar.com/sekiro_web_client.js?_123 这个地址是在前端创建客户端…

开源模型应用落地-CodeQwen模型小试-小试牛刀(一)

一、前言 代码专家模型是基于人工智能的先进技术,它能够自动分析和理解大量的代码库,并从中学习常见的编码模式和最佳实践。这种模型可以提供准确而高效的代码建议,帮助开发人员在编写代码时避免常见的错误和陷阱。 通过学习代码专家模型&…

【网络知识】光猫、路由器 和 交换机 的作用和区别?

数字信号:是指自变量是离散的、因变量也是离散的信号,这种信号的自变量用整数表示,因变量用有限数字中的一个数字来表示。在计算机中,数字信号的大小常用有限位的二进制数表示。 模拟信号:模拟信号是指用连续变化的物…

学习c#第26天 面向对象基础之类与对象

1.类 1.什么是类? 俗话说,“物以类聚,人以群分”。意思是同类的东西经常聚在一起,志同道合 的人相聚成群。前者说物,后者说人。这里以物来进行举例说明[见图]: 水果超市,所有同类的水果摆放在一起&#xf…

【机器学习与实现】线性回归分析

目录 一、相关和回归的概念(一)变量间的关系(二)Pearson(皮尔逊)相关系数 二、线性回归的概念和方程(一)回归分析概述(二)线性回归方程 三、线性回归模型的损…

vivado刷题笔记46

题目: Design a 1-12 counter with the following inputs and outputs: Reset Synchronous active-high reset that forces the counter to 1 Enable Set high for the counter to run Clk Positive edge-triggered clock input Q[3:0] The output of the counter c…

场外个股期权和场内个股期权的优缺点是什么?

场外个股期权和场内个股期权的优缺点 场外个股期权是指在沪深交易所之外交易的个股期权,其本质是一种金融衍生品,允许投资者在股票交易场所外以特定价格买进或卖出证券。场内个股期权是以单只股票作为标的资产的期权合约,其内在价值是基于标…

金融业开源软件应用 管理指南

金融业开源软件应用 管理指南 1 范围 本文件提供了金融机构在应用开源软件时的全流程管理指南,对开源软件的使用和管理提供了配套 组织架构、配套管理规章制度、生命周期流程管理、风险管理、存量管理、工具化管理等方面的指导。 本文件适用于金融机构规范自身对开…

工业物联网技术在生产流程中的应用及优势与挑战——青创智通

工业物联网解决方案-工业IOT-青创智通 随着科技的不断发展,物联网技术逐渐渗透到各个行业中,尤其是在工业领域,工业物联网的应用正在逐步重塑生产流程。本文将探讨工业物联网如何影响生产流程,并分析其带来的优势和挑战。 一、工…

Amazon Bedrock的进化:更多选择与新特性,助力生成式AI应用更快落地

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

leetcode-没有重复项的全排列-97

题目要求 思路 1.递归,如果num和n的元素个数一样就可以插入res中了,这个作为递归的结束条件 2.因为这个题是属于排列,并非组合,两者的区别是排列需要把之前插入的元素在回退会去,而组合不需要,因此会存在一…

YPay源支付Mini Pro免授权使用版v1.0

YPay源支付Mini Pro免授权使用版v1.0 ,修改host屏蔽Pro授权站,可有效防止因用户操作不当导致免授权程序无法执行时 执行授权官方的盗版入库代码,尽可能保证网站安全 1.安装SG14组件 注:仅防止二次开发添加授权 2.”/etc/host”文…

尊享面试100题(314.二叉树的垂直遍历python)

题目关键词,从左到右,从上到下,那么使用bfs宽度优先算法。 使用字典v保存每一列的值。 class Solution:def verticalOrder(self, root: Optional[TreeNode]) -> List[List[int]]:if not root: return []v defaultdict(list)qu deque()…

淘宝扭蛋机小程序开发:开启你的惊喜之旅

一、扭出新世界,惊喜不断 在这个充满无限可能的数字时代,淘宝扭蛋机小程序为你带来了一种全新的购物与娱乐体验。扭蛋机,这个充满童趣和惊喜的玩具,如今在我们的小程序中焕发出新的活力,为你带来一波又一波的惊喜与快…

WES-100B液晶数显式液压万能试验机

一、简介 主机为两立柱、两丝杠、油缸下置式,拉伸空间位于主机的上方,压缩、弯曲试验空间位于主机下横梁和工作台之间。测力仪表采用高清液晶显示屏,实验数据方便直观。 二、 传动系统 下横梁升降采用电机经减速器、链传动机构、丝杠副传动…

Redis开源社区持续壮大,华为云为Valkey项目注入新的活力

背景 今年3月21日,Redis Labs宣布从Redis 7.4版本开始,将原先比较宽松的BSD源码使用协议修改为RSAv2和SSPLv1协议,意味着 Redis在OSI(开放源代码促进会)定义下不再是严格的开源产品。Redis官方表示,开发者…

QT--1

类型界面 #include "mywidget.h"myWidget::myWidget(QWidget *parent): QWidget(parent) {//窗口相关设置this->resize(680,520);this->setFixedSize(680,520);this->setWindowTitle("Tim");this->setWindowFlag(Qt::FramelessWindowHint);th…
最新文章