Java實現(xiàn)動態(tài)獲取文件的絕對路徑
前言
我們知道在 Java 中讀取一些配置文件信息,是在開發(fā)中十分常用的要求。
例如:這里我們使用 JDBC 實例:連接MySQL 數(shù)據(jù)庫,讀取連接數(shù)據(jù)庫的 用戶名,密碼 。
如下是一個名為 jdbc.properties
的配置文件信息,以及存在目錄
package blogs.blogs8; import java.io.FileInputStream; import java.io.IOException; import java.util.Properties; public class IORead { public static void main(String[] args) { FileInputStream f = null; try { // 創(chuàng)建字節(jié)輸入流對象 // 在IDEA 中的默認(rèn)相對路徑是在 src 同級目錄下的 f = new FileInputStream("src/blogs/blogs8/jdbc.properties"); // 創(chuàng)建Map集合中的 Properties 對象 Properties properties = new Properties(); properties.load(f); // 通過 key 讀取對應(yīng)的鍵值對 String user = properties.getProperty("user"); System.out.println(user); String password = properties.getProperty("password"); System.out.println(password); } catch (IOException e) { e.printStackTrace(); } finally { // 關(guān)閉IO資源 if(f == null) { try { f.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
說明:
上述的讀取文件的方式,我們可以看到是 “完全沒有問題的” 可以讀取到對應(yīng)的配置信息,但是存在一個缺點(diǎn):就是移除性差。src 中是在 IDEA 這個編譯器中體現(xiàn)的,如果是在其它的編譯器中運(yùn)行的時候,很大的可能會報錯,原因是:這里我們使用的相對路徑是,在 IDEA中的,IDEA 中的默認(rèn)相對路徑是 在 project 下的也就是 src 的同級目錄。但是其它的系統(tǒng),或者編譯器就可能不是這個和 IDEA 中默認(rèn)相對路徑了。運(yùn)行程序時,就有可能會報錯:如下:找不到指定的文件。
上述這種方式:如果我們不寫相對路徑,而是寫絕對路徑的話,也是存在一個問題的。那就是因為該絕對路徑是寫死了的,不是動態(tài)獲取的,該路徑在 Windows 操作系統(tǒng)中是存在盤符的,所以寫絕對路徑的時候是需要帶上盤符(E盤,D盤的),但是如果該程序是運(yùn)行在其他操作系統(tǒng)中的話,比如 Linux 操作系統(tǒng)中是沒有盤符的說法的。所以就會出問題。無法跨平臺。
1. 優(yōu)化方式一:返回一個文件的絕對路徑
接下來說一種比較通用的一種路徑:即使代碼換位置了,這樣的代碼編寫的方式仍然是通用的。因為該文件的路徑是動態(tài)獲取的。
在Windows中的話,就以該系統(tǒng)的文件規(guī)則,動態(tài)獲取到的絕對路徑是帶盤符的,而 Linux系統(tǒng)中就以該系統(tǒng)的文件規(guī)則,獲取到的絕對路徑是不帶盤符的。 這就可以跨平臺了。
注意: 使用該方式的前提是:所讀取的文件必須是在 類路徑
下才行。如果不是在類路徑下,運(yùn)行程序時是會報錯:系統(tǒng)找不到指定的路徑
。
什么是類路徑 ?
類路徑也是一種特殊的相對路徑,只不過它相對的是class文件。在 IDEA 中的類路徑是在 src 目錄下的。重點(diǎn)記住它
該方式的核心代碼:
String path = Thread.currentThread().getContextClassLoader().getResource("db.properties").getPath(); /* 解釋: Thread.currentThread() 當(dāng)前線程對象 getContextClassLoader() 是線程對象的方法,可以獲取到當(dāng)前線程的類加載對象 getResource() 獲取資源:這是類加載器對象的方法,當(dāng)前線程的類加載器默認(rèn)從類的根路徑下加載資源。 getPath() 獲取當(dāng)文件的絕對路徑 */
1.1 情況一
所讀取的文件是直接存放在 src 的目錄下的,該文件的并沒有其它的的包。如下圖所示:可以直接寫文件名 + 文件名的后綴即可。
import java.io.FileInputStream; import java.io.IOException; import java.util.Properties; public class IORead { public static void main(String[] args) { String path = Thread.currentThread().getContextClassLoader().getResource("db.properties").getPath(); System.out.println(path); // 返回該文件的絕對路徑: } }
通過該方式獲取到指定文件的絕對路徑,再將該絕對路徑,作為參數(shù),創(chuàng)建FileInputStream
字節(jié)輸入流對象
import java.io.FileInputStream; import java.io.IOException; import java.util.Properties; public class IORead { public static void main(String[] args) { FileInputStream f = null; try { // 獲取到該配置文件的的絕對路徑 String path = Thread.currentThread().getContextClassLoader().getResource("db.properties").getPath(); // 通過該獲取的文件的絕對路徑創(chuàng)建 字節(jié)輸入流對象 f = new FileInputStream(path); // 創(chuàng)建Map集合中的 Properties 對象 Properties properties = new Properties(); properties.load(f); // 通過 key 讀取對應(yīng)的鍵值對 String user = properties.getProperty("user"); System.out.println(user); String password = properties.getProperty("password"); System.out.println(password); } catch (IOException e) { e.printStackTrace(); } finally { // 關(guān)閉IO資源 if (f != null) { try { f.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
也是可以讀取到文件中是在 src 目錄下。
1.2 情況二
當(dāng)所讀取的文件,是在 src 目錄下,但是該 src 目錄下還有其他的包(目錄),則不可以直接寫 “文件名+ 文件后綴名”了,而是需要寫明該 src 包(目錄)下的 相對路徑:如下圖所示的文件:該路徑名應(yīng)該是:blogs/blogs8/jdbc.properties
舉例:
import java.io.FileInputStream; import java.io.IOException; import java.util.Properties; public class IORead { public static void main(String[] args) { FileInputStream f = null; try { // 獲取到該配置文件的的絕對路徑,如下src目錄下還有目錄(包),需要指定 src目錄下/包下的哪個文件。 String path = Thread.currentThread().getContextClassLoader().getResource("blogs/blogs8/jdbc.properties").getPath(); // 通過該獲取的文件的絕對路徑創(chuàng)建 字節(jié)輸入流對象 f = new FileInputStream(path); // 創(chuàng)建Map集合中的 Properties 對象 Properties properties = new Properties(); properties.load(f); // 通過 key 讀取對應(yīng)的鍵值對 String user = properties.getProperty("user"); System.out.println(user); String password = properties.getProperty("password"); System.out.println(password); } catch (IOException e) { e.printStackTrace(); } finally { // 關(guān)閉IO資源 if (f != null) { try { f.close(); } catch (IOException e) { e.printStackTrace(); } } } }
2. 優(yōu)化方式二:返回一個 InputStream 字節(jié)輸入流
上述方式一:我們需要通過 :new 一個 FileInputStream 字節(jié)輸入流對象的方式,這里我們直接通過指定的文件名的,直接返回一個 InputStream 字節(jié)輸入流 ,不需要 new 。
同樣的:該讀取的文件必須是在類路徑下才行,這里的IDEA的類路徑是 src 目錄下
核心代碼如下:
// 直接以流的形式返回。 InputStream resourceAsStream = Thread.currentThread().getContextClassLoader(). getResourceAsStream("db.properties");
舉例:
import java.io.IOException; import java.io.InputStream; import java.util.Properties; public class IORead { public static void main(String[] args) { // 直接在 src目錄下沒有包含任何子目錄,可以直接寫文件名+ 后綴,而如果有子目錄,需要指明子目錄下的文件名+后綴名 InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"); // 創(chuàng)建 Properties 集合對象,通過流獲取指定配置文件中的鍵值對信息 Properties properties = new Properties(); try { properties.load(inputStream); } catch (IOException e) { e.printStackTrace(); } String user = properties.getProperty("user"); System.out.println(user); String password = properties.getProperty("password"); System.out.println(password); // 關(guān)閉IO資源 if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
3. 優(yōu)化方式三:java.util 包下提供了一個資源綁定器
上述兩個方式可以獲取到任意文件的信息。
但是以下這個方式三:就只能獲取到 類路徑下的以 .properties
后綴的配置文件信息了。
java.util
包下提供了一個資源綁定器,便于獲取屬性.properties
配置文件中的內(nèi)容。
該資源綁定器:只能綁定 xxx.properties
配置文件 ,并且這個文件必須在 類路徑下,這里的 IDEA 是 src 目錄下。
并且在寫路徑的時候,路徑后面的擴(kuò)展名不能寫,寫了會報錯: ``。因為既然只能讀取 properteis 后綴的文件,那就不用再多余的寫文件后綴名了。
如果在 src 目錄下的子目錄中的文件,需要指明是 src 下的哪個子目錄下的文件,同樣不要寫文件后綴名,不然報錯。
舉例:
import java.util.ResourceBundle; public class IORead { public static void main(String[] args) { ResourceBundle resourceBundle = ResourceBundle.getBundle("db"); String user = resourceBundle.getString("user"); System.out.println(user); String password = resourceBundle.getString("password"); System.out.println(password); } }
4. 總結(jié)
- 原始的方式:寫相對路徑的話,無法跨編譯器;因為不同的編譯器默認(rèn)相對的路徑是不同的。寫絕對路徑的話,無法跨平臺,因為不同操作系統(tǒng)的文件規(guī)則是不一樣的,比如 Windows系統(tǒng)中的絕對路徑是帶盤符(D盤,C盤),Linux 系統(tǒng)中的文件規(guī)則是不帶盤符的。當(dāng)在J Windows 操作系統(tǒng)中編寫的絕對路徑的Java程序,移植到到 Linux 操作系統(tǒng)中就會報錯。
- 靜態(tài)獲取的絕對路徑 和 動態(tài)獲取絕對路徑。
- 上述的三種優(yōu)化方式,都是動態(tài)獲取絕對路徑的,但是都是基于 類路徑下的文件才行的,不同所讀取的文件不在 類路徑下 是無法動態(tài)獲取到對應(yīng)絕對路徑的。
- 上述 :優(yōu)化方式1,優(yōu)化方式2 可以動態(tài)獲取到 類路徑下的任意文件信息。但是 優(yōu)化方式三:只能獲取到 類路徑下的以
.properties
后綴的配置文件信息了。 - 注意:優(yōu)化方式三:不可以寫文件后綴名,直接寫文件名就可以了。因為資源綁定器,就只能綁定
xxx.properties
配置文件 ,并且這個文件必須在 類路徑下。 - 如果類路徑下,比如:IDEA 中的 src 目錄就是類路徑,文件是直接在 src 類路徑下沒有包含子目錄的話,可以直接寫
文件名+文件后綴名
,如果文件是在 src 目錄下含有的子目錄下,則需要指明 類路徑 src 下的哪個子目錄的文件。
到此這篇關(guān)于Java實現(xiàn)動態(tài)獲取文件的絕對路徑的文章就介紹到這了,更多相關(guān)Java獲取文件絕對路徑內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
淺談Java內(nèi)存模型之happens-before
于存在線程本地內(nèi)存和主內(nèi)存的原因,再加上重排序,會導(dǎo)致多線程環(huán)境下存在可見性的問題。那么我們正確使用同步、鎖的情況下,線程A修改了變量a何時對線程B可見?下面小編來簡單介紹下2019-05-05Java日期毫秒值和常見日期時間格式相互轉(zhuǎn)換方法
這篇文章主要給大家介紹了關(guān)于Java日期毫秒值和常見日期時間格式相互轉(zhuǎn)換的相關(guān)資料,在Java的日常開發(fā)中,會隨時遇到需要對時間處理的情況,文中給出了詳細(xì)的示例代碼,需要的朋友可以參考下2023-07-07SpringBoot獲取配置文件內(nèi)容的幾種方式總結(jié)
大家都知道SpringBoot獲取配置文件的方法有很多,下面這篇文章主要給大家介紹了關(guān)于SpringBoot獲取配置文件內(nèi)容的幾種方式,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-02-02