springboot运行jar包,实现复制jar包resources下文件、文件夹(可支持包含子文件夹)到指定的目录
背景:
以jar包运行时,获取文件目录时,会报错;
idea运行不会报错。
代码:
//复制文件夹到指定路径下
String srcFilePath = Thread.currentThread().getContextClassLoader().getResource("").getPath()+ "/templates";
FileUtils.copyFolder(new File(srcFilePath), dir);
/*** 文件夹的复制* @param srcFile 源文件夹File对象* @param destFile 目标文件夹File对象* @throws IOException IOException*/public static void copyFolder(File srcFile, File destFile) throws IOException {//判断数据源File是否是文件if (srcFile.isDirectory()) {//在目的地下创建和数据源File名称一样的目录String srcFileName = srcFile.getName();File newFolder = new File(destFile, srcFileName);if (!newFolder.exists()) {newFolder.mkdir();}//获取数据源File下所有文件或者目录的File数组File[] listFiles = srcFile.listFiles();//遍历该File数组,得到每一个File对象for (File file : listFiles) {//把该File作为数据源File对象,递归调用复制文件夹的方法copyFolder(file, newFolder);}} else {//说明是文件,直接用字节流复制File newFile = new File(destFile, srcFile.getName());copyFile(srcFile, newFile);}}/*** 复制文件* @param srcFile 源文件* @param destFile 目标文件* @throws IOException IOException*/public static void copyFile(File srcFile, File destFile) throws IOException {BufferedInputStream bis = null;BufferedOutputStream bos = null;try {if (!destFile.getParentFile().exists()) {destFile.getParentFile().mkdirs();}if (!destFile.exists()) {destFile.createNewFile();}bis = new BufferedInputStream(new FileInputStream(srcFile));bos = new BufferedOutputStream(new FileOutputStream(destFile));int len;byte[] bys = new byte[1024];while ((len = bis.read(bys)) != -1) {bos.write(bys, 0, len);}} finally {if (null != bos) {try {bos.close();} catch (IOException e) {e.printStackTrace();}}if (null != bis) {try {bis.close();} catch (IOException e) {e.printStackTrace();}}}}
这行:bis = new BufferedInputStream(new FileInputStream(srcFile));
文件复制时,报错:
java.io.FileNotFoundException: file:/xxx/xxx.jar!/BOOT-INF/classes!/xxx/xxx (No such file or directory)
或
java.io.FileNotFoundException: file:\xxx\xxx.jar!\BOOT-INF\classes!\xxx\xxx (文件名、目录名或卷标语法不正确。)
问题产生原因:当我们使用文件路径访问文件时,该路径下的文件必须是可访问的,而jar文件本质是上是一个压缩文件,需要解压才能访问,所以程序会直接报错。
解决方案:
更改复制文件夹方式,不读文件路径,直接读取文件流。
以jar包运行时,不能使用resource.getFile()获取文件路径、判断是否为文件等,会报错:
java.io.FileNotFoundException: class path resource [xxx/xxx/] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:xxx.jar!/BOOT-INF/classes!/xxx/xxx这边使用resource.getDescription()进行获取文件路径,然后进行格式化处理。
FreeMarkerUtil工具类
import org.apache.commons.lang.StringUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.util.ClassUtils;import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;/*** 复制resource文件、文件夹*/
public class FreeMarkerUtil {/*** 复制path目录下所有文件,覆盖(jar)** @param path 文件目录 不能以/开头* @param newPath 新文件目录*/public static void copyFolderFromJarCover(String path, String newPath) throws IOException {if (!new File(newPath).exists()) {new File(newPath).mkdir();}if (path.contains("\\")) {path = path.replace("\\", "/");}if (path.startsWith("/")) {//以/开头,去掉/path = path.substring(1);}if (path.endsWith("/")) {//以/结尾,去掉/path = path.substring(0, path.length() - 1);}ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();//获取所有匹配的文件(包含根目录文件、子目录、子目录下的文件)Resource[] resources = resolver.getResources("classpath:" + path + "/**/");//打印有多少文件for (Resource resource : resources) {//文件名String filename = resource.getFilename();//以jar包运行时,不能使用resource.getFile()获取文件路径、判断是否为文件等,会报错://java.io.FileNotFoundException: class path resource [xxx/xxx/] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:xxx.jar!/BOOT-INF/classes!/xxx/xxx//文件路径//file [/xxx/xxx]String description = resource.getDescription();description = description.replace("\\", "/");//保留 /xxx/xxxdescription = description.replaceAll("(.*\\[)|(]$)", "").trim();//以“文件目录”进行分割,获取文件相对路径String[] descriptions = description.split(path + "/");if (descriptions.length > 1) {//获取文件相对路径,/xxx/xxxString relativePath = descriptions[1];//新文件路径String newFilePath = newPath + "/" + relativePath;if (FreeMarkerUtil.isDirectory(filename)) {//文件夹if (!new File(newFilePath).exists()) {new File(newFilePath).mkdir();}} else {//文件InputStream stream = resource.getInputStream();write2File(stream, newFilePath);}}}}/*** 复制path目录下所有文件,不覆盖(jar)** @param path 文件目录 不能以/开头* @param newPath 新文件目录*/public static void copyFolderFromJar(String path, String newPath) throws IOException {if (!new File(newPath).exists()) {new File(newPath).mkdir();}if (path.contains("\\")) {path = path.replace("\\", "/");}if (path.startsWith("/")) {//以/开头,去掉/path = path.substring(1);}if (path.endsWith("/")) {//以/结尾,去掉/path = path.substring(0, path.length() - 1);}ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();//获取所有匹配的文件(包含根目录文件、子目录、子目录下的文件)Resource[] resources = resolver.getResources("classpath:" + path + "/**/");//打印有多少文件for (Resource resource : resources) {//文件名String filename = resource.getFilename();//以jar包运行时,不能使用resource.getFile()获取文件路径、判断是否为文件等,会报错://java.io.FileNotFoundException: class path resource [xxx/xxx/] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:xxx.jar!/BOOT-INF/classes!/xxx/xxx//文件路径//file [/xxx/xxx]String description = resource.getDescription();description = description.replace("\\", "/");//保留 /xxx/xxxdescription = description.replaceAll("(.*\\[)|(]$)", "").trim();//以“文件目录”进行分割,获取文件相对路径String[] descriptions = description.split(path + "/");if (descriptions.length > 1) {//获取文件相对路径,/xxx/xxxString relativePath = descriptions[1];//新文件路径String newFilePath = newPath + "/" + relativePath;if (FreeMarkerUtil.isDirectory(filename)) {//文件夹if (!new File(newFilePath).exists()) {new File(newFilePath).mkdir();}} else {//文件File f = new File(newFilePath);if (!f.exists()) {InputStream stream = resource.getInputStream();write2File(stream, newFilePath);}}}}}/*** 复制文件(jar)** @param path 源文件路径* @param newPath 新文件路径*/public static void copyFileFromJar(String path, String newPath) throws IOException {//不读文件路径,直接读取文件流InputStream inputStream = ClassUtils.getDefaultClassLoader().getResourceAsStream(path);write2File(inputStream, newPath);}/*** 输入流写入文件** @param is 输入流* @param filePath 文件保存目录路径* @throws IOException IOException*/public static void write2File(InputStream is, String filePath) throws IOException {File destFile = new File(filePath);if (!destFile.getParentFile().exists()) {destFile.getParentFile().mkdirs();}if (!destFile.exists()) {destFile.createNewFile();}OutputStream os = new FileOutputStream(destFile);int len = 8192;byte[] buffer = new byte[len];while ((len = is.read(buffer, 0, len)) != -1) {os.write(buffer, 0, len);}os.close();is.close();}/*** 判断是否为目录、文件夹* @param filename 文件名* @return boolean*/public static boolean isDirectory(String filename) {if (StringUtils.isBlank(filename)) {return false;}//有后缀,是文件boolean contains = filename.contains(".");if (contains) {return false;}//是文件夹return true;}/*** 判断是否为目录、文件夹* @param path 文件路径* @return boolean*/public static boolean isDirectoryFromPath(String path) {if (StringUtils.isBlank(path)) {return false;}String newPath = path.replace("\\", "/");if (newPath.contains("/")) {newPath = newPath.substring(newPath.lastIndexOf("/"));}//有后缀,是文件;boolean contains = newPath.contains(".");if (contains) {return false;}//是文件夹return true;}public static void main(String[] args) throws IOException {//文件夹复制String path = "templates";String newPath = "D:/tmp";FreeMarkerUtil.copyFolderFromJarCover(path, newPath);//文件复制String filePath = "application.properties";String newFilePath = "D:/tmp/application.properties";FreeMarkerUtil.copyFileFromJar(filePath, newFilePath);}}
文件复制
同样道理,以jar包运行也会报错。
解决方案:
//文件复制
String filePath = "application.properties";
String newFilePath = "D:/tmp/application.properties";
FreeMarkerUtil.copyFileFromJar(filePath, newFilePath);
/*** 复制文件(jar)** @param path 源文件路径* @param newPath 新文件路径*/public static void copyFileFromJar(String path, String newPath) throws IOException {//不读文件路径,直接读取文件流InputStream inputStream = ClassUtils.getDefaultClassLoader().getResourceAsStream(path);write2File(inputStream, newPath);}
相关文章:
springboot运行jar包,实现复制jar包resources下文件、文件夹(可支持包含子文件夹)到指定的目录
背景: 以jar包运行时,获取文件目录时,会报错; idea运行不会报错。 代码: //复制文件夹到指定路径下 String srcFilePath Thread.currentThread().getContextClassLoader().getResource("").getPath() &…...
Webpack Bundle Analyzer包分析器
当我们需要分析打包文件dist里哪些资源可以进一步优化时,就可以使用包分析器插件webpack-bundle-analyzer。NPM上的介绍是使用交互式可缩放树图可视化 webpack 输出文件的大小。 我的是vue2项目。 1、webpack-bundle-analyzer插件的安装 $ npm install --save-dev…...
SQL-----STUDENT
【学生信息表】 【宿舍信息表】 【宿舍分配表】 为了相互关联,我们需要在表中添加外键。在宿舍分配表中添加用于关联学生信息表的外键 student_id,以及用于关联宿舍信息表的外键 dormitory_id; sql代码 -- 创建学生信息表 CREATE TABLE st…...
OpenCV入门——图像视频的加载与展示一些API
文章目录 OpenCV创建显示窗口OpenCV加载显示图片OpenCV保存文件利用OpenCV从摄像头采集视频从多媒体文件中读取视频帧将视频数据录制成多媒体文件OpenCV控制鼠标关于[np.uint8](https://stackoverflow.com/questions/68387192/what-is-np-uint8) OpenCV中的TrackBar控件TrackBa…...
Control的Invoke和BeginInvoke
近日,被Control的Invoke和BeginInvoke搞的头大,就查了些相关的资料,整理如下。感谢这篇文章对我的理解Invoke和BeginInvoke的真正含义 。 (一)Control的Invoke和BeginInvoke 我们要基于以下认识: (1&#x…...
什么是OpenCL?
什么是OpenCL? 1.概述 OpenCL(Open Computing Language 开放计算语言)是一种开放的、免版税的标准,用于超级计算机、云服务器、个人计算机、移动设备和嵌入式平台中各种加速器的跨平台并行编程。OpenCL是由Khronos Group创建和管理的。OpenCL使应用程序…...
AdaBoost:提升机器学习的力量
一、介绍 机器学习已成为现代技术的基石,为从推荐系统到自动驾驶汽车的一切提供动力。在众多机器学习算法中,AdaBoost(Adaptive Boosting的缩写)作为一种强大的集成方法脱颖而出,为该领域的成功做出了重大贡献。AdaBoo…...
Pikachu(皮卡丘靶场)初识XSS(常见标签事件及payload总结)
目录 1、反射型xss(get) 2、反射性xss(post) 3、存储型xss 4、DOM型xss 5、DOM型xss-x XSS又叫跨站脚本攻击,是HTML代码注入,通过对网页注入浏览器可执行代码,从而实现攻击。 1、反射型xss(get) Which NBA player do you like? 由…...
一则DNS被重定向导致无法获取MySQL连接处理
同事反馈xwik应用端报java exception 获取MySQL连接超时无法连接到数据库实例 经过告警日志发现访问进来的IP地址数据库端无法被解析,这里可以知道问题出现在Dns配置上了 通过以上报错检查/etc/resolve.conf 发现namesever 被重定向设置成了114.114.114.114 域名 …...
Vue3中如何使用this
import { getCurrentInstance, ComponentInternalInstance } from vuesetup() {// as ComponetInternalInstance表示类型断言,ts时使用。否则报错,proxy为nullconst { proxy } getCurrentInstance() as ComponetInternalInstanceproxy.$parentproxy.$re…...
7.jvm对象内存布局
目录 概述对象里的三个区对象头验证代码控制台输出分析 验证2代码控制台输出 实例数据对其填充 访问对象结束 概述 jvm对象内存布局详解。 相关文章在此总结如下: 文章地址jvm基本知识地址jvm类加载系统地址双亲委派模型与打破双亲委派地址运行时数据区地址运行时数…...
U-boot(一):Uboot命令和tftp
本文主要基于S5PV210探讨uboot。 uboot 部署:uboot(180~400K的裸机程序)在Flash(可上电读取)、OS在FLash(nand) 启动过程:上电后先执行uboot、uboot初始化DDR和Flash,将OS从Flash中读到DDR中启动OS,uboot结束 特点:…...
代码随想录算法训练营第五十三天丨 动态规划part14
1143.最长公共子序列 思路 本题和动态规划:718. 最长重复子数组 (opens new window)区别在于这里不要求是连续的了,但要有相对顺序,即:"ace" 是 "abcde" 的子序列,但 "aec" 不是 &quo…...
pdf增强插件 Enfocus PitStop Pro 2022 mac中文版功能介绍
Enfocus PitStop Pro mac是一款 Acrobat 插件,主要用于 PDF 预检和编辑。这个软件可以帮助用户检查和修复 PDF 文件中的错误,例如字体问题、颜色设置、图像分辨率等。同时,Enfocus PitStop Pro 还提供了丰富的编辑工具,可以让用户…...
uniapp app tabbar 页面默认隐藏
1.在page.json 中找到tabbar visible 默认为true,设为false则是不显示 uni.setTabBarItem({ index: 1, //列表索引 visible:true //显示或隐藏 })...
深度学习 YOLO 实现车牌识别算法 计算机竞赛
文章目录 0 前言1 课题介绍2 算法简介2.1网络架构 3 数据准备4 模型训练5 实现效果5.1 图片识别效果5.2视频识别效果 6 部分关键代码7 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 基于yolov5的深度学习车牌识别系统实现 该项目较…...
即时通讯技术文集(第23期):IM安全相关文章(Part12) [共15篇]
为了更好地分类阅读 52im.net 总计1000多篇精编文章,我将在每周三推送新的一期技术文集,本次是第23 期。 [- 1 -] 理论联系实际:一套典型的IM通信协议设计详解(含安全层设计) [链接] http://www.52im.net/thread-283-…...
为什么UI自动化难做?—— 关于Selenium UI自动化的思考
在快速迭代的产品、团队中,UI自动化通常是一件看似美好,实际“鸡肋”(甚至绝大部分连鸡肋都算不上)的工具。原因不外乎以下几点: 1 效果有限 通常只是听说过,就想去搞UI自动化的团队,心里都认…...
Python小白之“没有名称为xlwings‘的模块”
题外话:学习和安装Python的第一个需求就是整理一个Excel,需要读取和写入Excel 背景:取到的模板代码,PyCharm本地运行报错:没有名称为xlwings的模块 解决办法:这类报模板找不到的错,即是模块缺…...
RK3588 学习教程1——获取linux sdk
上手rk3588前,需要先拥有一块开发板,这样可以少走很多弯路。个人推荐买一块itx3588j的板子。挺好用,接口丰富,可玩性高。 sdk可以直接在firefly官网下载,不用管什么版本,下载下来后直接更新即可࿰…...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
基于Java+MySQL实现(GUI)客户管理系统
客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息,对客户进行统一管理,可以把所有客户信息录入系统,进行维护和统计功能。可通过文件的方式保存相关录入数据,对…...
使用LangGraph和LangSmith构建多智能体人工智能系统
现在,通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战,比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...
Ubuntu系统多网卡多相机IP设置方法
目录 1、硬件情况 2、如何设置网卡和相机IP 2.1 万兆网卡连接交换机,交换机再连相机 2.1.1 网卡设置 2.1.2 相机设置 2.3 万兆网卡直连相机 1、硬件情况 2个网卡n个相机 电脑系统信息,系统版本:Ubuntu22.04.5 LTS;内核版本…...
6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础
第三周 Day 3 🎯 今日目标 理解类(class)和对象(object)的关系学会定义类的属性、方法和构造函数(init)掌握对象的创建与使用初识封装、继承和多态的基本概念(预告) &a…...
yaml读取写入常见错误 (‘cannot represent an object‘, 117)
错误一:yaml.representer.RepresenterError: (‘cannot represent an object’, 117) 出现这个问题一直没找到原因,后面把yaml.safe_dump直接替换成yaml.dump,确实能保存,但出现乱码: 放弃yaml.dump,又切…...
【java】【服务器】线程上下文丢失 是指什么
目录 ■前言 ■正文开始 线程上下文的核心组成部分 为什么会出现上下文丢失? 直观示例说明 为什么上下文如此重要? 解决上下文丢失的关键 总结 ■如果我想在servlet中使用线程,代码应该如何实现 推荐方案:使用 ManagedE…...
SQL进阶之旅 Day 22:批处理与游标优化
【SQL进阶之旅 Day 22】批处理与游标优化 文章简述(300字左右) 在数据库开发中,面对大量数据的处理任务时,单条SQL语句往往无法满足性能需求。本篇文章聚焦“批处理与游标优化”,深入探讨如何通过批量操作和游标技术提…...
6.计算机网络核心知识点精要手册
计算机网络核心知识点精要手册 1.协议基础篇 网络协议三要素 语法:数据与控制信息的结构或格式,如同语言中的语法规则语义:控制信息的具体含义和响应方式,规定通信双方"说什么"同步:事件执行的顺序与时序…...
