中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

項目打包成jar后包無法讀取src/main/resources下文件怎么解決

發布時間:2022-04-02 13:42:55 來源:億速云 閱讀:1166 作者:iii 欄目:開發技術

這篇文章主要介紹“項目打包成jar后包無法讀取src/main/resources下文件怎么解決”,在日常操作中,相信很多人在項目打包成jar后包無法讀取src/main/resources下文件怎么解決問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”項目打包成jar后包無法讀取src/main/resources下文件怎么解決”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

    一、項目場景

    在項目中讀取文件時, 使用new File() 出現的一個坑以及解決流程
    這種問題不僅在本地文件讀取時會遇到, 而且在下載項目下 (例如: src/main/resources目錄下) 的文本時, 也會遇到,

    二、問題描述

    發現問題

    原來代碼
    該代碼功能是利用 common.io 包下的FileUtils來讀取文件, 放到一個字符串中

    String s = FileUtils.readFileToString(new File("src/main/resources/holiday.txt"), "utf-8");

    這種路徑書寫方式 new File("src/main/resources/holiday.txt") , 在本地運行沒問題,
    但是打包之后在服務器中運行出現了問題. 下面是錯誤截圖

    項目打包成jar后包無法讀取src/main/resources下文件怎么解決

    可以看到在服務器中日志提示: java.io.FileNotFoundException: File 'holiday.txt' does not exist
    即: 在打包后, 一開始配置的路徑src/main/resources下無法找到該文件

    分析問題

    項目在打包之后, 位于 resource目錄下的文件, 最常見的就是各種Spring配置文件就會打包在 BOOT-INF/classes 目錄下
    而FIle 在按照原來的文件路徑src/main/resources/holiday.txt'去尋找, 必然找不到文件, 因此會報文件找不到的異常

    項目打包成jar后包無法讀取src/main/resources下文件怎么解決

    在定位問題的過程中發現, 這里 提供了一個思路
    就是SpringBoot中所有文件都在jar包中,沒有一個實際的路徑,因此可以使用以下方式

        /**
         * 通過ClassPathResource類獲取,建議SpringBoot中使用
         * springboot項目中需要使用此種方法,因為jar包中沒有一個實際的路徑存放文件
         *
         * @param fileName
         * @throws IOException
         */
        public void function6(String fileName) throws IOException {
            ClassPathResource classPathResource = new ClassPathResource(fileName);
            InputStream inputStream = classPathResource.getInputStream();
            getFileContent(inputStream);
        }

    為什么使用 ClassPathResource 后, 可以找到打包后的文件路徑?

    上面代碼的核心就是: 實例化ClassPathResource 對象. 然后調用getInputStream 來獲取資源文件

    下面我們來分析這些代碼
    ClassPathResource 在實例化時, 會初始化類加載器 classLoader 并將項目所用到的所有路徑加載到類加載器 classLoader 中, 這些路徑包括: java運行環境的jar, Maven 項目中的jar, 以及當前項目打包后的jar等(如下圖)

    項目打包成jar后包無法讀取src/main/resources下文件怎么解決

    classPathResource.getInputStream 在獲取資源文件時, 因為上面我們初始化了一個classLoader.
    所以classLoader不為空, 因此會執行 getResourceAsStream 方法, 我們來追一下這個方法

    項目打包成jar后包無法讀取src/main/resources下文件怎么解決

    getResourceAsStream 方法中的getResource是實際的業務處理方法, 我們繼續深入

    項目打包成jar后包無法讀取src/main/resources下文件怎么解決

    getResource 方法如下圖, 實際的功能就是遞歸調用自己, 去不斷遍歷 parent 下的路徑, 獲取對應的資源文件
    那么 parent 又是誰呢? 我們繼續往下看

    項目打包成jar后包無法讀取src/main/resources下文件怎么解決

    看到這里我們豁然開朗, 這個神秘的 parent 就是類加載器classLoader!!!
    因此getResource 方法就是去不斷遍歷我們在ClassPathResource實例化時, 創建的類加載器下面的路徑!!!(對應第1點)

    項目打包成jar后包無法讀取src/main/resources下文件怎么解決

    三、解決方案

    原來讀取文件的代碼如下

    String s = FileUtils.readFileToString(new File("src/main/resources/holiday.txt"), "utf-8");

    去查看 File 的構造函數, 看能否通過 InputStream 來構造
    從下圖看是不行的

    項目打包成jar后包無法讀取src/main/resources下文件怎么解決

    方案一

    并且我們發現 org.apache.commons.io沒有提供ClassPathResource 作為入參的讀取文件的方法.
    因此我們必須手寫讀取文件的方法

    項目打包成jar后包無法讀取src/main/resources下文件怎么解決

    手寫的代碼如下
    主要注意 Resource resource = new ClassPathResource(fileName); is = resource.getInputStream();

        /**
         * Java讀取txt文件的內容
         *
         * @param fileName resources目錄下文件名稱(無需帶目錄)
         * @return 將每行作為一個單位放到list中
         */
        public static List<String> readTxtFile(String fileName) {
            List<String> listContent = new ArrayList<>();
            InputStream is = null;
            InputStreamReader isr = null;
            BufferedReader br = null;
            String encoding = "utf-8";
            try {
                Resource resource = new ClassPathResource(fileName);
                is = resource.getInputStream();
                isr = new InputStreamReader(is, encoding);
                br = new BufferedReader(isr);
                String lineTxt = null;
                while ((lineTxt = br.readLine()) != null) {
                    listContent.add(lineTxt);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    br.close();
                    isr.close();
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return listContent;
        }

    方案二

    這種方式對代碼入侵較小, 核心還是利用 common.io 下的 FileUtils, 具體方法是
    利用FileUtils將ClassPathResource.getInputStream 得到的輸入流復制到臨時文件中, 然后讀取這個臨時文件
    這種方式缺點是: 需要創建臨時文件, 如果待讀取文件過大, 則重新創建文件和復制操作會消耗一定的空間和時間, 影響性能

      //方式二 利用FileUtils將ClassPathResource.getInputStream 得到的輸入流復制到臨時文件中
      Resource resource = new ClassPathResource("holiday.txt");
      InputStream inputStream = resource.getInputStream();
      File tempFile = File.createTempFile("temp", ".txt");
      FileUtils.copyInputStreamToFile(inputStream, tempFile);
      
      String s = FileUtils.readFileToString(tempFile, StandardCharsets.UTF_8);

    意外出現

    到這里又出現了一個問題, 就是我用的測試項目因為在 maven 里面指定了某些格式的文件. 如下配置
    因為指定了banner.txt 以及 xml 與 properties結尾的文件作為資源被打包. 所以文件 holiday.txt 運行后還是訪問不到
    有問題的pom.xml文件如下

    	<!-- 資源拷貝插件,實現在打包時自動拷貝java目錄下以及resources目錄下的xml的配置文件 -->
    		<resources>
    			<resource>
    				<directory>src/main/java</directory>
    				<includes>
    					<include>**/*.xml</include>
    				</includes>
    			</resource>
    			<resource>
    				<directory>src/main/resources</directory>
    				<includes>
    					<include>**/*.xml</include>
    					<include>**/*.properties</include>
    					<include>**/banner.txt</include>
    				</includes>
    			</resource>
    		</resources>

    打包后資源文件截圖如下, 從該圖中可以看到 holiday.txt 沒有被打包進來

    項目打包成jar后包無法讀取src/main/resources下文件怎么解決

    程序運行之后的錯誤截圖

    項目打包成jar后包無法讀取src/main/resources下文件怎么解決

    我們修改下指定打包的配置 <include>**/*.txt</include>
    這樣配置后, 我們就可以將類路徑下的所有txt 文件打包進行項目中了, 打包之后文件位置如下圖
    或者我們可以去除項目中下面的代碼配置, 這樣做會默認打包 resources 下面的所有文件

    	<!-- 資源拷貝插件,實現在打包時自動拷貝java目錄下以及resources目錄下的xml的配置文件 -->
    		<resources>
    			<resource>
    				<directory>src/main/java</directory>
    				<includes>
    					<include>**/*.xml</include>
    				</includes>
    			</resource>
    			<resource>
    				<directory>src/main/resources</directory>
    				<includes>
    					<include>**/*.xml</include>
    					<include>**/*.properties</include>
    					<include>**/*.txt</include>
    				</includes>
    			</resource>
    		</resources>

    修改pom文件后, 重新打包后資源文件(從這里可以看到 holiday.txt 被打包進來 )

    項目打包成jar后包無法讀取src/main/resources下文件怎么解決

    到此,關于“項目打包成jar后包無法讀取src/main/resources下文件怎么解決”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    jar
    AI

    会东县| 吉安县| 大荔县| 扎兰屯市| 瑞安市| 五常市| 塔城市| 台江县| 南昌县| 瓦房店市| 马尔康县| 朝阳县| 陕西省| 汾阳市| 九龙坡区| 孙吴县| 香格里拉县| 于都县| 青海省| 虹口区| 沂南县| 封开县| 武山县| 行唐县| 河北区| 丰县| 金乡县| 云安县| 汝南县| 嫩江县| 阜康市| 乡城县| 怀宁县| 历史| 鲁山县| 阿拉善右旗| 浮山县| 凤冈县| 卓资县| 沅陵县| 延长县|