1. 前言
下面的corejava項目下,labs-v2ch02模塊下,有4個文件,1.properties、2.properties、3.properties、4.properties。
當我們需要使用這4個文件的時候,怎樣創建文件對象呢?
2. 基本知識
(1) 不同的操作系統,文件的分隔符不同:
Linux下:”/”
Window下:”\”
Java中通用表示方法:System.getProperty(“file.separator”);
(2) java.io.*包下,File以及Path,只是文件或路徑的抽象表示,並不一定實際存在。
如 File file = new File(“a.txt”); 表示在jvm啓動路徑下,新建a.txt文件,在寫入文件前,並不存在。
(3) 相對路徑指的是相對JVM的啓動路徑。
舉個例子:假設有一java源文件Example.java在d盤根目錄下。我們進入命令行窗口,進入到d盤根目錄下,然後用“javac Example.java”來編譯此文件,編譯無錯後,會在d盤根目錄下自動生成”Example.class”文件。我們再調用”java Example”來運行該程。此時我們已經啓動了一個jvm,這個jvm是在d盤根目錄下被啓動的,所以此jvm所加載的程序中File類的相對路徑也就是相對這個路徑的,即d盤根目錄D:\。
搞清了這些,我們可以使用相對路徑來創建文件,例如:
File file = new File(“a.tx”);
file.createNewFile();
假設jvm是在”D:\”下啓動的,那麼a.txt就會生成在D:\a.txt;
2. 獲取源碼路徑下文件
前面我們說過,JAVA中文件路徑是相對JVM的啓動路徑的,對於簡單的JAVA項目,其JVM是在項目名稱下啓動的。“.”或”./”代表當前目錄,這個目錄也就是jvm啓動路徑。
package com.geo.v2ch02;
import java.io.File;
/**
* 獲取模塊下文件
* @author galen
* @date 2020-4-18
* */
public class modelPath {
public static void main(String[] args) {
try {
// "./"表示默認啓動路徑,即jvm路徑,對於簡單項目,JVM是在項目名稱下啓動的,
File file1 = new File("./labs-v2ch02/1.properties");
File file2 = new File("./labs-v2ch02/src/2.properties");
File file3 = new File("./labs-v2ch02/src/com/geo/v2ch02/3.properties");
File file4 = new File("./labs-v2ch02/src/com/geo/v2ch02/sub/4.properties");
System.out.println(file1.exists() + ",file1:" + file1.getCanonicalPath());
System.out.println(file2.exists() + ",file2:" + file2.getCanonicalPath());
System.out.println(file3.exists() + ",file3:" + file3.getCanonicalPath());
System.out.println(file4.exists() + ",file4:" + file4.getCanonicalPath());
} catch (Exception e) {
e.printStackTrace();
}
}
}
運行結果(注意獲取到的都是源碼路徑下的文件):
3. 獲取父級路徑
“.”或”./”代表當前目錄,這個目錄也就是jvm啓動路徑。"…\"、"…/"代表當前目錄的上級目錄,getParent()代表當前文件或目錄的上級目錄。
package com.geo.v2ch02;
import java.io.File;
/**
* 獲取模塊下文件
* @author galen
* @date 2020-4-18
* */
public class parentPath {
public static void main(String[] args) {
try {
//注意".\\"與"./"在這裏效果一樣,建議用"./"與生產環境(一般爲linux)語義一致
File file5 = new File(".\\test1.txt");
File file6 = new File("./test1.txt");
File file7 = new File("..\\test1.txt");
File file8 = new File("../test1.txt");
File file9 = new File(file8.getParent()+"/test1.txt");
System.out.println(file5.exists() + ",file5:" + file5.getCanonicalPath());
System.out.println(file6.exists() + ",file6:" + file6.getCanonicalPath());
System.out.println(file7.exists() + ",file7:" + file7.getCanonicalPath());
System.out.println(file8.exists() + ",file8:" + file8.getCanonicalPath());
System.out.println(file9.exists() + ",file9:" + file9.getCanonicalPath());
} catch (Exception e) {
e.printStackTrace();
}
}
}
運行結果:注意觀察輸出的文件路徑。
4. 獲取發佈目錄下文件
上面創建文件的方式太過於繁瑣,所以對於package內的文件,我們採用getResource()、或者getClassLoader().getResource()獲取,對於2.properties和2.properties的獲取,我們傾向於採取下面的方法:
File file2 = new File(getResourcePath.class.getResource("/2.properties").toURI());
File file3 = new File(getResourcePath.class.getResource(“3.properties”).toURI());
或者:
File file4 = new File(getResourcePath.class.getClassLoader().getResource("").toURI());
File file5 = new File(getResourcePath.class.getClassLoader().getResource(“com/geo/v2ch02/3.properties”).toURI());
package com.geo.v2ch02;
import java.io.File;
/**
* 獲取模塊下文件
* @author galen
* @date 2020-4-18
* */
public class getResourcePath {
public static void main(String[] args) {
try {
//path 不以’/'開頭時,默認是從此類所在的包下取資源;path 以’/'開頭時,則是從ClassPath根下獲取;
File file2 = new File(getResourcePath.class.getResource("/2.properties").toURI());
File file3 = new File(getResourcePath.class.getResource("3.properties").toURI());
//使用class.getClassLoader(),當目錄或者文件不存在時,會報錯
File file4 = new File(getResourcePath.class.getClassLoader().getResource("").toURI());
File file5 = new File(getResourcePath.class.getClassLoader().getResource("com/geo/v2ch02/3.properties").toURI());
System.out.println(file2.exists() + ",file2:" + file2.getCanonicalPath());
System.out.println(file3.exists() + ",file3:" + file3.getCanonicalPath());
System.out.println(file4.exists() + ",file4:" + file4.getCanonicalPath());
System.out.println(file5.exists() + ",file5:" + file5.getCanonicalPath());
} catch (Exception e) {
e.printStackTrace();
}
}
}
輸出結果:
從結果來看【TestMain.class.getResource("/") == t.getClass().getClassLoader().getResource("")】
對於web項目 springmvc【未驗證】
Tomcat中的情況,如果在tomcat中運行web應用,此時,如果我們在某個類中使用如下代碼:
File f = new File(".");
String absolutePath = f.getAbsolutePath();
System.out.println(absolutePath);
那麼輸出的將是tomcat下的bin目錄.我的機器就D:\Java\apache-tomcat-8.5.32-windows-x64\apache-tomcat-8.5.32\bin.,由此可以看出tomcat服務器是在bin目錄下啓動jvm的,其實是在bin目錄下的“catalina.bat”文件中啓動jvm的。
對於web項目 springboot框架
對於springboot項目,輸出路徑爲配置的target/classes目錄
5. getPath()、getAbsolutePath()、getCanonicalPath()的區別
getPath()獲取的是新建文件時的路徑,例如:
File file1 = new File(".\test1.txt");通過getPath()獲取的是.\test1.txt
File file2 = new File(“D:\Text.txt”);通過getPath()獲取的是D:\Text.txt
getAbsolutePath()獲取的是文件的絕對路徑,返回當前目錄的路徑+構造file時候的路徑,例如:
File file3 = new File(".\test1.txt");通過getAbsolutePath()獲取的是D:\open source\gitee\corejava.\test1.txt
getCanonicalPath()獲取的也是文件的絕對路徑,而且把…或者.這樣的符號解析出來,例如:
File file4 = new File("…\src\test1.txt");通過getCanonicalPath()獲取的是D:\open source\gitee\src\test1.txt
package com.geo.v2ch02;
import java.io.File;
/**
* 獲取模塊下文件
* @author galen
* @date 2020-4-18
* */
public class testPath {
public static void main(String[] args) {
try {
File file1 = new File(".\\test1.txt");
File file2 = new File("D:\\Text.txt");
File file3 = new File(".\\test1.txt");
File file4 = new File("..\\src\\test1.txt");
System.out.println("file1:" + file1.getPath());
System.out.println("file2:" + file2.getPath());
System.out.println("file3:" + file3.getAbsolutePath());
System.out.println("file4:" + file4.getCanonicalPath());
} catch (Exception e) {
e.printStackTrace();
}
}
}
本文源碼地址:
java基礎 corejava
本文多參考:
Java中文件的相對路徑與絕對路徑