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

溫馨提示×

溫馨提示×

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

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

Java和IDEA中文件打包的示例分析

發布時間:2021-07-29 10:14:58 來源:億速云 閱讀:179 作者:小新 欄目:開發技術

這篇文章主要介紹Java和IDEA中文件打包的示例分析,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

問題:想在IDEA中引用相對路徑,但是找不到文件。

項目目錄結構

當前項目的路徑為:D:\source\java\test\

項目結構如下

Java和IDEA中文件打包的示例分析

當前路徑

面對無法使用相對路徑找到資源文件的問題,首先想到的解決辦法是先瞄一眼IDEA在執行時給Java環境設定的當前路徑在哪,也就是說看看我們在使用相對路徑時到底是相對于哪里的。

應該咋寫呢?下面是Java API中的一些描述。

默認情況下, java.io包中的類始終會根據當前用戶目錄解析相對路徑名。 該目錄由系統屬性user.dir ,通常是調用Java虛擬機的目錄。

根據上面的信息,可以想到兩個辦法來獲得當前路徑,第一種辦法是向Java中傳遞空字符串,這是一個比較hack的方法,按照相對路徑來解析的話,自然會被解析成當前目錄。

File f1 = new File(""); // 空字符串,相當于當前路徑
System.out.println(f1.getAbsolutePath());

第二種辦法,直接獲取系統屬性中的user.dir

System.out.println(System.getProperty("user.dir"));

兩種辦法得到的結果一致:

Java和IDEA中文件打包的示例分析

也就是說,當前目錄指向項目的根目錄,如果你想要獲取src中的一個文件的話,需要使用src/文件名,而如果該文件在某個包下的話,則需要使用src/完整包路徑/文件名

現在我在src下創建一個文件text1.txt,寫入內容HELLO , WORLD

Java和IDEA中文件打包的示例分析

File f2 = new File("src/text1.txt");
LineNumberReader reader2 = new LineNumberReader(new FileReader(f2));
System.out.println(reader2.readLine());

結果

Java和IDEA中文件打包的示例分析

這樣寫好嗎?

我們的Java代碼最終會被打包上傳到目標平臺,如某個服務器上,打包的代碼應該只包含編譯后的文件目錄,在IDEA中就是那個out目錄,其它的文件都不會出現在目標平臺上,到那個時候,你不再擁有當前項目編寫時的目錄結構,你的程序運行時所在的當前路徑也不再是現在這個。

簡單來說,我們寫出了依賴環境的代碼,這個代碼不保證程序運行在生產環境下的時候還可以正常執行,而且通常是無法正常執行。

唯一的辦法,就是我們在IDEA編譯時,告訴它有些文件,請你幫我打包到out目錄中,然后我再想辦法去out目錄中找,這下就不會出問題了。

JavaAPI中有這樣一個方法,它被明確說明是用來干這個事的就是ClassLoader中的getResource,下面是API中的說明

尋找給定名字的資源文件。一個資源文件可以是一些能夠被class代碼以一種獨立于代碼位置的方式進行訪問的數據(圖像、聲音、文字等)

我們先看看使用這個方法是相對于哪個路徑,采用的辦法和new File("")大同小異。

String path = Main.class.getClassLoader().getResource("").getPath();
System.out.println(path);

結果如下

Java和IDEA中文件打包的示例分析

它已經找到了我們打包后的二進制代碼所在的位置,這下就可以相對于二進制代碼的位置讀寫文件了,不再依賴當前環境。

注意,ClassLoader.getResourceAsStream和Class.getResourceAsStream有些細微的區別,見JAVA 筆記 ClassLoader.getResourceAsStream() 與 Class.getResourceAsStream()的區別

將文件打包到二進制代碼位置

創建文件夾,mark directory as -> Resources Root

Java和IDEA中文件打包的示例分析o

在其中創建text2.txt,寫入HELLO , RESOURCES

然后這樣去讀

LineNumberReader r3 = new LineNumberReader(
        new InputStreamReader(Main.class.getClassLoader().getResourceAsStream("text2.txt"))
);
System.out.println(r3.readLine());

這里使用了ClassLoader.getResource的一個變體getResourceAsStream,它的作用就是返回的是一個流,而非URL。我們所做的就是獲取當前類的ClassLoader,通過它獲取資源文件,轉換成LineNumberReader。

讀取成功,也就是說,在resources文件夾下的文件,IDEA會自動幫我們打包到二進制代碼的位置

Java和IDEA中文件打包的示例分析

其他

src中的文件

如果我們去看out文件夾下的文件結構,你就會發現,除了resources/text2.txt,我們之前在src下創建的text1.txt也被打包到這個位置了。也就是說,我們可以通過同樣的方式去讀取src下的文件。

D:\source\java\test\out>wsl tree .
.
└── production
    └── test
        ├── io
        │   └── lilpig
        │       └── test
        │           └── Main.class
        ├── text1.txt
        └── text2.txt

5 directories, 3 files

LineNumberReader r4 = new LineNumberReader(
        new InputStreamReader(Main.class.getClassLoader().getResourceAsStream("text1.txt"))
);
System.out.println(r4.readLine());

讀取成功

Java和IDEA中文件打包的示例分析

Thread.currentThread.getContextClassLoader

在多線程應用中,有可能你編寫的類的類加載器和實際加載resources文件夾的類加載器不是同一個,這會導致你的代碼無法獲取到資源文件,使用Thread.currentThread.getContextClassLoader能規避這個問題。具體的原理涉及到Java中的類加載機制的委托模型,這部分的內容原理性太強,我已經忘得差不多了,就不露怯了。

我們編寫的大部分后端應用,都是多線程應用,我們自己感知不到,那是因為多線程代碼被封裝在框架中,所以無論如何,使用Thread.currentThread.getContextClassLoader總比使用Main.class.getClassLoader更好。

并且,Thread.currentThread.getContextClassLoader更加具有一致性,你可以輕易的編寫一個工具方法來簡化代碼(無論如何Thread.currentThread返回的總是當前調用者所在的線程)。而如果用之前的方法,每一個類的類名都不同,你在一個類中寫的是Main.class.getClassLoader在另一個類中寫的又是Other.class.getClassLoader,這不一致的代碼會讓我們難以編寫一個通用的工具類。

框架

在框架中,資源文件夾都是默認被創建好的,有的可能叫static,有的可能叫resources......而且,有可能編譯后的目錄不是out,而是target,甚至會被打包成war包等。

我們要做的不是管它打包后在哪,而是直接往框架給你指定好的資源文件夾里面放文件就行,剩下的交給框架。

并且在框架中,隨處可見Thread.currentThread.getClassLoader().getResource...這樣的代碼。

以上是“Java和IDEA中文件打包的示例分析”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

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

AI

嘉祥县| 岗巴县| 玉林市| 冕宁县| 南开区| 文水县| 河北省| 清涧县| 京山县| 闽侯县| 新营市| 赤水市| 新闻| 云安县| 葫芦岛市| 大关县| 灵寿县| 兰考县| 聂荣县| 东乡县| 当雄县| 太白县| 泾源县| 东台市| 桦川县| 黄冈市| 武平县| 丹棱县| 安龙县| 平江县| 柳江县| 茶陵县| 同江市| 襄垣县| 昂仁县| 灵川县| 佳木斯市| 灵丘县| 锦州市| 酉阳| 博爱县|