目錄
在開發環境中運行,如eclips
在src目錄下
可以用絕對路徑和相對路徑來讀取,絕對路徑爲文件在磁盤的存放位置,這裏暫且不討論。
用相對路徑可按如下操作獲取文件資源:
File file = new File("src/main/resources/properties/basecom.properties");
InputStream in = new FileInputStream(file);
也可以通過類加載方式:
//讀取根目錄下的tmp(src/):
// 第一種方法
InputStream in = App.class.getResourceAsStream("/tmp");
// 第二種方法
InputStream in =ClassLoader.getSystemClassLoader().getResourceAsStream("tmp");
//讀取App類同級目錄下的tmp(src/space/yukai)
// 第一種方法
InputStream in = App.class.getResourceAsStream("tmp");
// 第二種方法
InputStream in =ClassLoader.getSystemClassLoader().getResourceAsStream("space/yukai/tmp");
//第三種方法
InputStream in = App.class.getResourceAsStream("/space/yukai/tmp");
//讀取MyClassloader同級目錄下的tmp(src/space/yukai/classloader):
// 第一種方法
InputStream in = App.class.getResourceAsStream("classloader/tmp");
// 第二種方法
InputStream in =ClassLoader.getSystemClassLoader().getResourceAsStream("space/yukai/classloader/tmp");
//第三種方法
InputStream in = App.class.getResourceAsStream("/space/yukai/classloader/tmp");
在非src目錄下
lib與src同級,想獲取lib目錄下的文件
File file = new File("./lib");
System.out.println(file.getAbsolutePath());
File[] listFiles = file.listFiles();
以jar包形式運行,linux系統
在src目錄下
當將工程導出jar包或war包時可用以下方法獲取
使用Class.getResource或者是ClassLoader.getResourceAsStream()將文件內容放到InputStream中
String s1 = this.getClass().getResource("/log4j.properties").getPath();
或者爲:
String s1 = CodeTest.class.getResource("/log4j.properties").getPath();
注意,使用class的getRescource時,要注意路徑前要加"/",即根目錄,此處的根目錄是src
若像如下使用:
String class_str = this.getClass().getResource("logback.xml").getPath();
則會出錯如下:
使用ClassLoader時,如下:
this.getClass().getClassLoader().getResource()
在使用ClassLoader時,路徑前面不能加"/",使用相對路徑。
public void readProperties(){
String ss = TempTest.class.getResource("/").getPath();
System.out.println(ss);
String s = new File(ss).getParentFile().getPath();
System.out.println(s);
String system_str = System.getProperty("user.dir");
System.out.println(system_str);
}
運行結果如下:
將上述readProperties函數打包爲jar包在命令行使用java -jar TempTest.jar運行時,結果如下:
由此可見,打包成jar包時和在ide中直接運行的結果並不一樣,所以在jar包中的class類要訪問自己jar包中的資源文件時,應該使用Class.getResource或者是getResourceAsStream放在InputStream中,再進行訪問。但是該方法只能訪問到src下的資源文件,因爲其根目錄對應的就是src,無法訪問到項目根目錄下src外的文件,如上述項目結構圖中的blackWhite中的文件無法訪問到,
關於class.getResource && classloader.getResource 的區別。
源碼中:Class.getResourceAsStream(String name)
public InputStream getResourceAsStream(String name) {
name = resolveName(name);
ClassLoader cl = getClassLoader0();
if (cl==null) {
// A system class.
return ClassLoader.getSystemResourceAsStream(name);
}
return cl.getResourceAsStream(name);
}
上面的代碼可以看出, Class.getResourceAsStream(String name) 最終還是調用了 classloader.getResourceAsStream(String name) 。但是兩者還是有一些區別的,注意 name =resolveName(name)這一行,Class.getResourceAsStream(String name)在這裏做了一些處理:Class.resolveName(String name)
通過測試類進行測試:
public class App {
public static void main(String[] args) {
System.out.println("App.class.getClassLoader().getResource(\"\") : " +
App.class.getClassLoader().getResource(""));
System.out.println("App.class.getClassLoader().getResource(\"/\") : " +
App.class.getClassLoader().getResource("/"));
System.out.println("App.class.getResource(\"\") : " + App.class.getResource(""));
System.out.println("App.class.getResource(\"/\") : " + App.class.getResource("/"));
}
}
結果如下:
App.class.getClassLoader().getResource("") :
file:/D:/workspace/eclipse/cluster/TestClassloader/bin/
App.class.getClassLoader().getResource("/") : null
App.class.getResource("") :
file:/D:/workspace/eclipse/cluster/TestClassloader/bin/space/yukai/
App.class.getResource("/") : file:/D:/workspace/eclipse/cluster/TestClassloader/bin/
calssloder.getResource("")方法返回了classpath根路徑(eclipse工程中,編譯生成的類文件存放在/bin目錄下);
calssloder.getResource("/")方法返回null,說明calssloder.getResource不支持以"/"開頭的參數;
class.getResource("")方法返回了App.class所在的路徑;
class.getResource("/")與calssloder.getResource("")表現一致,返回了classpath的根路徑
在非src目錄下,但在jar包內
如圖想打jar包後能繼續訪問lib中的json文件,可以用JarFile類來實現。
package com.test.jar;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class ReadSource {
public static void main(String[] args) throws Exception {
String path = ReadSource.class.getProtectionDomain().getCodeSource().getLocation().getPath();//獲取jar包的絕對路徑
path = java.net.URLDecoder.decode(path, "UTF-8");//轉換處理中文及空格,但是如果路徑中包含中文,就會變成帶“%xx%xx”格式的字符串。所以應該這樣寫纔對:
System.out.println("path: "+path);
JarFile localJarFile = new JarFile(new File(path));
Enumeration<JarEntry> entries = localJarFile.entries();
while (entries.hasMoreElements()) {
JarEntry jarEntry = entries.nextElement();
System.out.println(jarEntry.getName());
String innerPath = jarEntry.getName();
if(innerPath.contains(".json")&& !innerPath.contains("jar")){
InputStream inputStream =
ReadSource.class.getClassLoader().getResourceAsStream(innerPath);
BufferedReader br = new BufferedReader(new
InputStreamReader(inputStream));
String line="";
while((line=br.readLine())!=null){
System.out.println(innerPath+"內容爲:"+line);
}
}
}
}
}
結果:
在jar包外
比如在jar包同級目錄下有名爲testInfo的文件夾,
File file = new File("./testInfo");可獲取該文件夾對象。
file.getAbsolutePath();可獲取該文件夾對象的絕對路徑。
jar包訪問第三方依賴,的類路徑配置
手動配置MANITAST.MF中的class_path配置,即需要的第三方jar包
打包可執行jar包時,MANIFEST.MF總是個讓人頭疼的東西,經常出現這種那種問題。
一個例子:
Manifest-Version: 1.0
Main-Class: test.Main
Class-Path: ./ ./lib/commons-collections-3.2.jar ./lib/commons-dbcp-1.2.2.jar ./lib/commons-lang-2.3.jar ./lib/commons-logging-1.1.jar
各部分解釋:
Manifest-Version MF文件版本號
Main-Class 包含main方法的類
Class-Path 執行這個jar包時的ClassPath
以下是需要注意的各個要點:
- Manifest-Version、Main-Class和Class-Path後面跟着一個英文的冒號,冒號後面必須跟着一個空格,然後纔是版本號、類和ClassPath。
- Class-Path中的各項應使用空格分隔,不是逗號或分號。
- Class-Path中如果有很多項,寫成一行打包的時候會報錯line too long,這時需要把Class-Path分多行寫。注意:從第二行開始,必須以兩個空格開頭,三個以上我沒試過,不過不用空格開頭和一個空格開頭都是不行的,我已經試過了。
- Class-Path寫完之後最後一定要有一個空行。
5. jar包內有些配置文件想放在jar包外面,比如文件config.properties:如果這個文件是以路徑方式載入的,比如new file("./config/config.properties"),那麼將config.properties放在jar包相同目錄下的config目錄下即可,也就是說“./”路徑等價於jar包所在目錄;如果這個文件是以ClassPath下的文件這種方式載入的,比如在Spring中載入classpath:config.properties,則在MF文件的配置文件的ClassPath中添加“./”,然後將這個配置文件與jar包放在同一個目錄即可,當然也可以在MF文件的配置文件的ClassPath中添加“./config/”,然後把配置文件都放在jar包相同目錄下的config目錄下。