如何讀取運行jar中引用jar中的文件

1.問題發現

? ? ? ?項目中有個common包資源文件,然后springboot項目引用了common,那么我們要怎么讀取這個資源了。這里需要考慮三個場景,idea運行時、common jar獨立運行時、springboot引用common后運行時。

2.問題解決

2.1.idea運行時

 ProtectionDomain protectionDomain = LibPaths.class.getProtectionDomain();CodeSource codeSource = protectionDomain.getCodeSource();if (codeSource != null) {String jarPath = codeSource.getLocation().getPath();jarPath = jarPath.replaceFirst("^nested:", "");if(!jarPath.endsWith(".jar")){System.out.println("idea運行時classes路徑");}

2.2.common jar運行時?

public static String getUrl(){ProtectionDomain protectionDomain = LibPaths.class.getProtectionDomain();CodeSource codeSource = protectionDomain.getCodeSource();if (codeSource != null) {String jarPath = codeSource.getLocation().getPath();jarPath = jarPath.replaceFirst("^nested:", "");System.out.println("JAR 文件路徑: " + jarPath);if(jarPath != null){int index = jarPath.indexOf(".jar");String destDir = jarPath;if(index != -1){destDir = new File(jarPath.substring(0, index+4)).getParent();}if(jarPath.endsWith(".jar")){copyJarCuToOut(jarPath,destDir)}else{System.out.println("idea運行時classes路徑");}}
}public static void copyJarCuToOut(String jarPath,String destDir) throws IOException {File file = new File(destDir + File.separator + "test");if(!file.exists()){file.mkdirs();copyResourcesFromJar(jarPath,destDir, true);}else{System.out.println(file.getPath() + "已存在");}
}/*** 將 JAR 中指定路徑下的所有文件復制到目標目錄** @param jarFilePath   JAR 文件的路徑* @param resourcePath  JAR 中的資源路徑(例如 "resources/")* @param destDir       目標輸出目錄* @throws IOException  如果復制過程中出現錯誤*/
public static void copyResourcesFromJar(String jarFilePath, String resourcePath, String destDir) throws IOException {try (JarFile jarFile = new JarFile(jarFilePath)) {Enumeration<JarEntry> entries = jarFile.entries();while (entries.hasMoreElements()) {JarEntry entry = entries.nextElement();if (entry.getName().startsWith(resourcePath) && !entry.isDirectory() && ( entry.getName().endsWith(".cu") || entry.getName().endsWith(".cu.h"))) {// 構建目標路徑Path destPath = Paths.get(destDir + File.separator + entry.getName().substring(resourcePath.length()));// 復制文件try (InputStream is = jarFile.getInputStream(entry);OutputStream os = Files.newOutputStream(destPath)) {byte[] buffer = new byte[1024];int len;while ((len = is.read(buffer)) > 0) {os.write(buffer, 0, len);}}System.out.println("已復制: " + entry.getName() + " 到 " + destPath);}}}
}

2.3.springboot jar運行時??

public static String getUrl(){ProtectionDomain protectionDomain = LibPaths.class.getProtectionDomain();CodeSource codeSource = protectionDomain.getCodeSource();if (codeSource != null) {String jarPath = codeSource.getLocation().getPath();jarPath = jarPath.replaceFirst("^nested:", "");System.out.println("JAR 文件路徑: " + jarPath);if(jarPath != null){int index = jarPath.indexOf(".jar");String destDir = jarPath;if(index != -1){destDir = new File(jarPath.substring(0, index+4)).getParent();}if(jarPath.endsWith(".jar")){copyJarCuToOut(jarPath,destDir)}else{System.out.println("idea運行時classes路徑");}}
}public static void copyJarCuToOut(String jarPath,String destDir) throws IOException {File file = new File(destDir + File.separator + "test");if(!file.exists()){file.mkdirs();copyResourcesFromMultipleJar(jarPath,destDir, true);}else{System.out.println(file.getPath() + "已存在");}
}/*** 將 JAR 中指定路徑下的所有文件復制到目標目錄** @param jarFilePath   JAR 文件的路徑* @param resourcePath  JAR 中的資源路徑(例如 "resources/")* @param destDir       目標輸出目錄* @throws IOException  如果復制過程中出現錯誤*/
public static void copyResourcesFromMultipleJar(String jarFilePath, String resourcePath, String destDir) throws IOException {// 1. 分離路徑部分String[] parts = jarFilePath.split("/!");if (parts.length < 2) {throw new IllegalArgumentException("無效的嵌套 JAR 路徑格式");}// 2. 解析外層 JAR 路徑(去掉開頭的 / 和 !/)String outerJarPath = parts[0];String innerJarEntry = parts[1].replace("!/", "");System.out.println("###################" + outerJarPath);// 3. 打開外層 JARtry (JarFile outerJar = new JarFile(outerJarPath)) {// 4. 獲取內層 JAR 的 EntryJarEntry innerEntry = outerJar.getJarEntry(innerJarEntry);if (innerEntry == null) {throw new FileNotFoundException("內層 JAR 不存在: " + innerJarEntry);}System.out.println("innerJarEntry###################" + innerJarEntry);try (InputStream innerIs = outerJar.getInputStream(innerEntry); JarInputStream innerJar = new JarInputStream(innerIs)) {JarEntry entry;while ((entry = innerJar.getNextJarEntry()) != null) {if (entry.getName().startsWith(resourcePath) && !entry.isDirectory()) {// 構建目標路徑Path destPath = Paths.get(destDir + File.separator + entry.getName().substring(resourcePath.length()));// 復制文件try (OutputStream os = Files.newOutputStream(destPath)) {byte[] buffer = new byte[1024];int len;while ((len = innerJar.read(buffer)) > 0) {os.write(buffer, 0, len);}}System.out.println("已復制: " + entry.getName() + " 到 " + destPath);}}}}}

2.4.完整代碼

package com.omega.common.lib;import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;public class LibPaths {static {try {// 獲取 ProtectionDomain 和 CodeSourceProtectionDomain protectionDomain = LibPaths.class.getProtectionDomain();CodeSource codeSource = protectionDomain.getCodeSource();if (codeSource != null) {String jarPath = codeSource.getLocation().getPath();jarPath = jarPath.replaceFirst("^nested:", "");System.out.println("JAR 文件路徑: " + jarPath);if(jarPath != null){int index = jarPath.indexOf(".jar");String destDir = jarPath;if(index != -1){destDir = new File(jarPath.substring(0, index+4)).getParent();}if(jarPath.endsWith(".jar")){copyJarCuToOut(jarPath,destDir, false);}else if(jarPath.endsWith(".jar!/")){copyJarCuToOut(jarPath,destDir, true);}LIB_PATH = destDir + File.separator + "test";}else{System.out.println("JAR 文件路徑為空");}} else {System.out.println("無法獲取 JAR 路徑(可能來自系統類加載器)");}} catch (IOException e) {e.printStackTrace();}}public static void copyJarCuToOut(String jarPath,String destDir, boolean multiple) throws IOException {File file = new File(destDir + File.separator + "test");if(!file.exists()){file.mkdirs();if(multiple){copyResourcesFromMultipleJar(jarPath, "test", file.getPath());}else{copyResourcesFromJar(jarPath, "test", file.getPath());}}else{System.out.println(file.getPath() + "已存在");}}/*** 將 JAR 中指定路徑下的所有文件復制到目標目錄** @param jarFilePath   JAR 文件的路徑* @param resourcePath  JAR 中的資源路徑(例如 "resources/")* @param destDir       目標輸出目錄* @throws IOException  如果復制過程中出現錯誤*/public static void copyResourcesFromJar(String jarFilePath, String resourcePath, String destDir) throws IOException {try (JarFile jarFile = new JarFile(jarFilePath)) {Enumeration<JarEntry> entries = jarFile.entries();while (entries.hasMoreElements()) {JarEntry entry = entries.nextElement();if (entry.getName().startsWith(resourcePath) && !entry.isDirectory() && ( entry.getName().endsWith(".cu") || entry.getName().endsWith(".cu.h"))) {// 構建目標路徑Path destPath = Paths.get(destDir + File.separator + entry.getName().substring(resourcePath.length()));// 復制文件try (InputStream is = jarFile.getInputStream(entry);OutputStream os = Files.newOutputStream(destPath)) {byte[] buffer = new byte[1024];int len;while ((len = is.read(buffer)) > 0) {os.write(buffer, 0, len);}}System.out.println("已復制: " + entry.getName() + " 到 " + destPath);}}}}/*** 將 JAR 中指定路徑下的所有文件復制到目標目錄** @param jarFilePath   JAR 文件的路徑* @param resourcePath  JAR 中的資源路徑(例如 "resources/")* @param destDir       目標輸出目錄* @throws IOException  如果復制過程中出現錯誤*/public static void copyResourcesFromMultipleJar(String jarFilePath, String resourcePath, String destDir) throws IOException {// 1. 分離路徑部分String[] parts = jarFilePath.split("/!");if (parts.length < 2) {throw new IllegalArgumentException("無效的嵌套 JAR 路徑格式");}// 2. 解析外層 JAR 路徑(去掉開頭的 / 和 !/)String outerJarPath = parts[0];String innerJarEntry = parts[1].replace("!/", "");System.out.println("###################" + outerJarPath);// 3. 打開外層 JARtry (JarFile outerJar = new JarFile(outerJarPath)) {// 4. 獲取內層 JAR 的 EntryJarEntry innerEntry = outerJar.getJarEntry(innerJarEntry);if (innerEntry == null) {throw new FileNotFoundException("內層 JAR 不存在: " + innerJarEntry);}System.out.println("innerJarEntry###################" + innerJarEntry);try (InputStream innerIs = outerJar.getInputStream(innerEntry); JarInputStream innerJar = new JarInputStream(innerIs)) {JarEntry entry;while ((entry = innerJar.getNextJarEntry()) != null) {if (entry.getName().startsWith(resourcePath) && !entry.isDirectory()) {// 構建目標路徑Path destPath = Paths.get(destDir + File.separator + entry.getName().substring(resourcePath.length()));// 復制文件try (OutputStream os = Files.newOutputStream(destPath)) {byte[] buffer = new byte[1024];int len;while ((len = innerJar.read(buffer)) > 0) {os.write(buffer, 0, len);}}System.out.println("已復制: " + entry.getName() + " 到 " + destPath);}}}}}}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/912591.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/912591.shtml
英文地址,請注明出處:http://en.pswp.cn/news/912591.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【學習方法】框架質疑學習法:破解專業學習的“知識厚度”困境

今天博主給大家分享一個&#xff0c;我自己發明了一個比較高效的學習方法,名叫“框架質疑學習法” 本文提出的框架質疑學習法&#xff08;Framework Questioning Learning Method&#xff09;為本文作者&#xff0c;也就是我&#xff0c;董翔首次提出。 在軟件專業的學習中&a…

spring-ai 1.0.0 學習(十七)——MCP Client

之前學過了工具調用&#xff08;spring-ai 1.0.0 學習&#xff08;十二&#xff09;——工具調用_springai 1.0 如何判斷調用哪一個tool工具-CSDN博客&#xff09;&#xff0c;今天來看一下MCP MCP是什么 MCP全稱是模型上下文協議&#xff0c;有點繞&#xff0c;通俗點理解&a…

Git 運行.sh文件

1.在項目文件中右擊 Open Git Bash here 顯示&#xff08;base&#xff09;環境 2.激活conda環境 3.復制.sh文件的相對路徑 4.將路徑復制到git終端 先輸入sh和空格&#xff0c;然后右擊后選paste&#xff0c;不要直接ctrl v 5.開始運行

MySQL InnoDB 引擎中的聚簇索引和非聚簇索引有什么區別?

MySQL InnoDB 引擎中的聚簇索引和非聚簇索引有什么區別&#xff1f; 主要解答詳細解答1. **聚簇索引&#xff08;Clustered Index&#xff09;**2. **非聚簇索引&#xff08;Non-Clustered Index / Secondary Index&#xff09;**3. **對比總結**4. **流程圖&#xff08;查詢過…

[2025CVPR]DE-GANs:一種高效的生成對抗網絡

目錄 引言:數據高效GAN的困境 核心原理:動態質量篩選機制 1. 判別器拒絕采樣(DRS)的再思考 2. 質量感知動態拒絕公式 (1)質量感知階段 (2)動態拒絕階段 模型架構:輕量化設計 技術突破:三大創新點 1. 首創訓練階段DRS 2. 動態拒絕機制 3. 質量重加權策略 …

[面試] 手寫題-數組轉樹

示例數據&#xff1a; const arr [{ id: 1, parentId: null, name: Root },{ id: 2, parentId: 1, name: Child 1 },{ id: 3, parentId: 1, name: Child 2 },{ id: 4, parentId: 2, name: Grandchild 1 }, ]目標生成&#xff1a; const tree [{id: 1,name: Root,children: …

CertiK《Hack3d:2025年第二季度及上半年Web3.0安全報告》(附報告全文鏈接)

CertiK《Hack3d&#xff1a;2025年第二季度及上半年Web3.0安全報告》現已發布&#xff0c;報告顯示&#xff1a;僅2025年上半年&#xff0c;因安全事件導致的損失接近25億美元&#xff1b;截至目前&#xff0c;總損失已超過去年全年水平。整體來看&#xff0c;Web3.0安全形勢依…

反向傳播 梯度消失

反向傳播 backpropagation 反向傳播&#xff08;Backpropagation&#xff09; 是神經網絡訓練中的一種核心算法&#xff0c;用于通過計算誤差并將其傳播回網絡&#xff0c;從而更新神經網絡的參數。通過反向傳播&#xff0c;網絡能夠在每次迭代中逐步調整其參數&#xff08;例…

京東外賣服務商加入方案對比!選擇本地生活服務商系統的優勢,到底在哪?

自入局之日起&#xff0c;京東外賣似乎就一直熱衷于給人驚喜&#xff1a; 先是在上線時規定了“2025年5月1日前入駐的商家&#xff0c;全年免傭金”和“僅限品質堂食商家入駐”&#xff1b; 再是宣布了要為外賣騎手繳納五險一金&#xff0c;并承擔其中的所有成本&#xff1b;…

【RTSP從零實踐】4、使用RTP協議封裝并傳輸AAC

&#x1f601;博客主頁&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客內容&#x1f911;&#xff1a;&#x1f36d;嵌入式開發、Linux、C語言、C、數據結構、音視頻&#x1f36d; &#x1f923;本文內容&#x1f923;&a…

Bootstrap 安裝使用教程

一、Bootstrap 簡介 Bootstrap 是一個開源的前端框架&#xff0c;由 Twitter 開發&#xff0c;旨在快速開發響應式、移動優先的 Web 頁面。它包含 HTML、CSS 和 JavaScript 組件&#xff0c;如按鈕、導航欄、表單等。 二、Bootstrap 安裝方式 2.1 使用 CDN&#xff08;推薦入…

Java學習第二部分——基礎語法

目錄 一.數據類型 &#xff08;一&#xff09;數值類型&#xff08;用于存儲數字&#xff0c;包括整數和浮點數&#xff09; 1. **整數類型** 2. **浮點類型** &#xff08;二&#xff09;非數值類型&#xff08;非數值類型用于存儲非數字數據&#xff09; 1. **char** 2…

Redis分布式鎖核心原理源碼

文章目錄 概述一、Redis實現分布式鎖1.1、第一版1.2、第二版1.3、第三版1.3、第四版 二、Redisson實現分布式鎖核心源碼分析2.1、加鎖核心源碼2.2、鎖續期核心源碼2.3、重試機制核心源碼2.4、解鎖核心源碼 總結 概述 傳統的單機鎖&#xff08;Synchronized&#xff0c;Reentran…

關于vue2使用elform的rules校驗

在使用vue2開發項目的時候使用element組件的el-form大多數情況都需要用到必填項校驗 舉個栗子&#xff1a; <el-form :model"ruleForm" :rules"rules" ref"ruleForm" label-width"100px" class"demo-ruleForm"><e…

langchain從入門到精通(二十六)——RAG優化策略(四)問題分解策略提升負責問題檢索準確率

1. LangChain 少量示例提示模板 在與 LLM 的對話中&#xff0c;提供少量的示例被稱為 少量示例&#xff0c;這是一種簡單但強大的指導生成的方式&#xff0c;在某些情況下可以顯著提高模型性能&#xff08;與之對應的是零樣本&#xff09;&#xff0c;少量示例可以降低 Prompt…

Nuxt.js基礎(Tailwind基礎)

??1. 按鈕組件實現?? ??傳統 CSS <!-- HTML --> <button class"btn-primary">提交</button><!-- CSS --> <style>.btn-primary {background-color: #3490dc;padding: 0.5rem 1rem;border-radius: 0.25rem;color: white;transi…

[C語言]存儲結構詳解

C語言存儲結構總結 在C語言中&#xff0c;數據根據其類型和聲明方式被存儲在不同的內存區域。以下是各類數據存儲位置的詳細總結&#xff1a; 內存五大分區 存儲區存儲內容生命周期特點代碼區(.text)程序代碼(機器指令)整個程序運行期只讀常量區(.rodata)字符串常量、const全…

【實戰】 容器中Spring boot項目 Graphics2D 畫圖中文亂碼解決方案

場景 架構&#xff1a;spring boot 容器技術&#xff1a;docker 服務器&#xff1a;阿里云 開發環境&#xff1a;windows10 IDEA 一、問題 服務器中出現Graphics2D 畫圖中文亂碼 本地環境運行正常 二、原因 spring boot 容器中沒有安裝中文字體 三、解決方案 安裝字體即可 …

深入淺出:Vue2 數據劫持原理剖析

目錄 一、什么是數據劫持&#xff1f; 二、核心 API&#xff1a;Object.defineProperty 三、Vue2 中的數據劫持實現 1. 對象屬性的劫持 2. 嵌套對象的處理 3. 數組的特殊處理 四、結合依賴收集的完整流程 五、數據劫持的局限性 六、Vue3 的改進方案 總結 一、什么是數…

數據湖 vs 數據倉庫:數據界的“自來水廠”與“瓶裝水廠”?

數據湖 vs 數據倉庫&#xff1a;數據界的“自來水廠”與“瓶裝水廠”&#xff1f; 說起“數據湖”和“數據倉庫”&#xff0c;很多剛入行的朋友都會覺得&#xff1a; “聽起來好高大上啊&#xff01;但到底有啥區別啊&#xff1f;是湖更大還是倉庫更高端&#xff1f;” 我得說…