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流的方式讀?。?/p>

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

? ? }

}? ?


程序調(diào)用代碼如下:

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過來的代碼

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容