SpringBoot 讀取jar包下resource中的文件夾

前段時間薄啥,在基于springboot開發(fā)過程中垄惧,遇到一個問題:程序需要讀取resource下的某個目錄的全部文件绰寞,而且需要能以File的方式讀取滤钱。但是, 打包后铜靶,springboot項目就成了jar包了他炊,讀取文件痊末,會報錯: ... cannot be resolved to absolute file path because it does not reside in the file system:jar:file: ....? 舌胶。

一般情況下,我們讀取resource下的某個文件辆它,可以這樣通過IO流的方式讀让誊浴:

Resource resource =new ClassPathResource(fileName);

InputStream is = resource.getInputStream();

當時,有些時候片吊,需要使用File:resource.getFile() 协屡,這時俏脊,在jar包下就會報上面的錯誤》粝可是爷贫,如果是文件夾怎么辦呢?

經(jīng)過網(wǎng)上的一番查詢补憾,確定了一個方案:把jar包中的文件漫萄,先存到一個臨時文件夾下,然后通過臨時文件夾盈匾,可以實現(xiàn)以File的方式讀取腾务,文件讀取完成后,刪除臨時文件目錄窑睁。

文件復制代碼如下:

import lombok.extern.log4j.Log4j2;

import org.springframework.core.io.ClassPathResource;

import org.springframework.core.io.Resource;

import java.io.*;

import java.net.URL;

import java.util.Enumeration;

import java.util.HashMap;

import java.util.Map;

import java.util.zip.ZipEntry;

import java.util.zip.ZipFile;

@Log4j2

public class FileUtils {

? ? /**

? ? * 復制文件到目標目錄

? ? * @param resourcePath resource的文件夾路徑

? ? * @param tmpDir 臨時目錄

? ? * @param fileType 文件類型

? ? */

? ? public static void copyJavaResourceDir2TmpDir(String resourcePath, String tmpDir, FileType fileType) {

? ? ? ? Map<String, Object> fileMap = new HashMap<>();

? ? ? ? if (resourcePath.endsWith("/")) {

? ? ? ? ? ? resourcePath = resourcePath.substring(0, resourcePath.lastIndexOf("/"));

? ? ? ? }

? ? ? ? try {

? ? ? ? ? ? Enumeration resources = null;

? ? ? ? ? ? try {

? ? ? ? ? ? ? ? resources = Thread.currentThread().getContextClassLoader().getResources(resourcePath);

? ? ? ? ? ? } catch (Exception ex) {

? ? ? ? ? ? ? ? ex.printStackTrace();

? ? ? ? ? ? }

? ? ? ? ? ? if (resources == null || !resources.hasMoreElements()) {

? ? ? ? ? ? ? ? resources = FileUtils.class.getClassLoader().getResources(resourcePath);

? ? ? ? ? ? }

? ? ? ? ? ? while (resources.hasMoreElements()) {

? ? ? ? ? ? ? ? URL resource = (URL) resources.nextElement();

? ? ? ? ? ? ? ? if (resource.getProtocol().equals("file")) { // resource是文件

? ? ? ? ? ? ? ? ? ? continue;

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? String[] split = resource.toString().split(":");

? ? ? ? ? ? ? ? String filepath = split[2];

? ? ? ? ? ? ? ? if (OperatingSystem.isWindows()) {

? ? ? ? ? ? ? ? ? ? filepath = filepath + ":" + split[3];

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? String[] split2 = filepath.split("!");

? ? ? ? ? ? ? ? String zipFileName = split2[0];

? ? ? ? ? ? ? ? ZipFile zipFile = new ZipFile(zipFileName);

? ? ? ? ? ? ? ? Enumeration entries = zipFile.entries();

? ? ? ? ? ? ? ? while (entries.hasMoreElements()) {

? ? ? ? ? ? ? ? ? ? ZipEntry entry = (ZipEntry) entries.nextElement();

? ? ? ? ? ? ? ? ? ? String entryName = entry.getName();

? ? ? ? ? ? ? ? ? ? if (entry.isDirectory()) {

? ? ? ? ? ? ? ? ? ? ? ? continue;

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? if (entryName.contains(resourcePath) && entryName.endsWith(fileType.toString().toLowerCase())) {

? ? ? ? ? ? ? ? ? ? ? ? String dir = entryName.substring(0, entryName.lastIndexOf("/"));

? ? ? ? ? ? ? ? ? ? ? ? if (!dir.endsWith(resourcePath)) { // 目標路徑含有子目錄

? ? ? ? ? ? ? ? ? ? ? ? ? ? dir = dir.substring(dir.indexOf(resourcePath) + resourcePath.length() + 1);

? ? ? ? ? ? ? ? ? ? ? ? ? ? if (dir.contains("/")) { // 多級子目錄

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? String[] subDir = dir.split("/");

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Map<String, Object> map = fileMap;

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? for (String d : subDir) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? map = makeMapDir(map, d);

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? map.putAll(readOneFromJar(zipFile.getInputStream(entry), entryName));

? ? ? ? ? ? ? ? ? ? ? ? ? ? } else { //一級子目錄

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (fileMap.get(dir) == null) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? fileMap.put(dir, new HashMap<String, Object>());

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ((Map<String, Object>) fileMap.get(dir))

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? .putAll(readOneFromJar(zipFile.getInputStream(entry), entryName));

? ? ? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? } else { // 目標路徑不含子目錄

? ? ? ? ? ? ? ? ? ? ? ? ? ? fileMap.putAll(readOneFromJar(zipFile.getInputStream(entry), entryName));

? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? } catch (Exception e) {

? ? ? ? ? ? log.error("讀取resource文件異常:", e);

? ? ? ? } finally {

? ? ? ? ? ? try {

? ? ? ? ? ? ? ? // 寫到目標緩存路徑

? ? ? ? ? ? ? ? createFile(fileMap, tmpDir);

? ? ? ? ? ? } catch (Exception e) {

? ? ? ? ? ? ? ? log.error("創(chuàng)建臨時文件異常:", e);

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? private static void createFile(Map<String, Object> fileMap, String targetDir) {

? ? ? ? fileMap.forEach((key, value) -> {

? ? ? ? ? ? if (value instanceof Map) {

? ? ? ? ? ? ? ? createFile((Map<String, Object>) value, targetDir + File.separator + key);

? ? ? ? ? ? } else {

? ? ? ? ? ? ? ? createNewFile(targetDir + File.separator + key, value.toString());

? ? ? ? ? ? }

? ? ? ? });

? ? }

? ? public static void createNewFile(String filePath, String value) {

? ? ? ? try {

? ? ? ? ? ? File file = new File(filePath);

? ? ? ? ? ? if (!file.exists()) {

? ? ? ? ? ? ? ? File parentDir = file.getParentFile();

? ? ? ? ? ? ? ? if (!parentDir.exists()) {

? ? ? ? ? ? ? ? ? ? parentDir.mkdirs();

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? file.createNewFile();

? ? ? ? ? ? }

? ? ? ? ? ? PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "utf-8")));

? ? ? ? ? ? out.write(value);

? ? ? ? ? ? out.flush();

? ? ? ? ? ? out.close();

? ? ? ? } catch (Exception e) {

? ? ? ? ? ? log.error("創(chuàng)建文件異常:", e);

? ? ? ? }

? ? }

? ? private static Map<String, Object> makeMapDir(Map<String, Object> fileMap, String d) {

? ? ? ? if (fileMap.get(d) == null) {

? ? ? ? ? ? fileMap.put(d, new HashMap<String, Object>());

? ? ? ? }

? ? ? ? return (Map<String, Object>) fileMap.get(d);

? ? }

? ? public static Map<String, String> readOneFromJar(InputStream inputStream, String entryName) {

? ? ? ? Map<String, String> fileMap = new HashMap<>();

? ? ? ? try (Reader reader = new InputStreamReader(inputStream, "utf-8")) {

? ? ? ? ? ? StringBuilder builder = new StringBuilder();

? ? ? ? ? ? int ch = 0;

? ? ? ? ? ? while ((ch = reader.read()) != -1) {

? ? ? ? ? ? ? ? builder.append((char) ch);

? ? ? ? ? ? }

? ? ? ? ? ? String filename = entryName.substring(entryName.lastIndexOf("/") + 1);

? ? ? ? ? ? fileMap.put(filename, builder.toString());

? ? ? ? } catch (Exception ex) {

? ? ? ? ? ? log.error("讀取文件異常:", ex);

? ? ? ? }

? ? ? ? return fileMap;

? ? }

? ? public enum FileType {

? ? ? ? XSD, TXT, XLS, XLSX, DOC, DOCX, XML, SQL, PROPERTIES, SH

? ? }

}? ?


程序調用代碼如下:

String tmpDir = System.getProperty("user.dir") + File.separator +"tmp";

try {

? ? FileUtils.copyJavaResourceDir2TmpDir("xsd", tmpDir, FileUtils.FileType.XSD);

? ? loadXsd(new File(tmpDir));

} catch (Exception e) {

? ? logger.error("加載xsd文件異常:", e);

} finally {

? ? FileUtils.delete(tmpDir);

}

這樣,就不用每次部署實例的時候葵孤,都把需要文件和jar一起部署了担钮,方便多了。

OperatingSystem是Filnk中copy過來的代碼

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末尤仍,一起剝皮案震驚了整個濱河市箫津,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌宰啦,老刑警劉巖苏遥,帶你破解...
    沈念sama閱讀 219,110評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異赡模,居然都是意外死亡田炭,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評論 3 395
  • 文/潘曉璐 我一進店門漓柑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來教硫,“玉大人叨吮,你說我怎么就攤上這事∷簿兀” “怎么了茶鉴?”我有些...
    開封第一講書人閱讀 165,474評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長景用。 經(jīng)常有香客問我涵叮,道長,這世上最難降的妖魔是什么伞插? 我笑而不...
    開封第一講書人閱讀 58,881評論 1 295
  • 正文 為了忘掉前任割粮,我火速辦了婚禮,結果婚禮上媚污,老公的妹妹穿的比我還像新娘舀瓢。我一直安慰自己,他們只是感情好杠步,可當我...
    茶點故事閱讀 67,902評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著榜轿,像睡著了一般幽歼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谬盐,一...
    開封第一講書人閱讀 51,698評論 1 305
  • 那天甸私,我揣著相機與錄音,去河邊找鬼飞傀。 笑死皇型,一個胖子當著我的面吹牛,可吹牛的內容都是我干的砸烦。 我是一名探鬼主播弃鸦,決...
    沈念sama閱讀 40,418評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼幢痘!你這毒婦竟也來了唬格?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,332評論 0 276
  • 序言:老撾萬榮一對情侶失蹤颜说,失蹤者是張志新(化名)和其女友劉穎购岗,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體门粪,經(jīng)...
    沈念sama閱讀 45,796評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡喊积,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,968評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了玄妈。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片乾吻。...
    茶點故事閱讀 40,110評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡髓梅,死狀恐怖,靈堂內的尸體忽然破棺而出溶弟,到底是詐尸還是另有隱情女淑,我是刑警寧澤,帶...
    沈念sama閱讀 35,792評論 5 346
  • 正文 年R本政府宣布辜御,位于F島的核電站鸭你,受9級特大地震影響,放射性物質發(fā)生泄漏擒权。R本人自食惡果不足惜袱巨,卻給世界環(huán)境...
    茶點故事閱讀 41,455評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望碳抄。 院中可真熱鬧愉老,春花似錦、人聲如沸剖效。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽璧尸。三九已至咒林,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間爷光,已是汗流浹背垫竞。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蛀序,地道東北人欢瞪。 一個月前我還...
    沈念sama閱讀 48,348評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像徐裸,于是被迫代替她去往敵國和親遣鼓。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,047評論 2 355

推薦閱讀更多精彩內容