前言
最近做项目,出现一件特别不能理解的事情,文件的实际路径与绝对路径差别很大。其中绝对路径差距很大。当设置user.dir系统变量时,绝对路径就是不对的。
demo
模拟奇特路径的demo,可以看到AbsolutePath和文件真实的路径相差太远了
public class FileUtils {
public static void main(String[] args) {
File file = new File(".");
System.out.println(file.getAbsolutePath());
Arrays.stream(file.listFiles()).forEach(p -> System.out.println(p.getAbsolutePath()));
// Arrays.stream(file.listFiles()).forEach(p -> System.out.println(p.getPath()));
// Arrays.stream(file.list()).forEach(System.out::println);
// System.out.println(file.getAbsolutePath());
}
}
可以看到路径是
但是当VM参数设置-Duser.dir=xxx,
这里以 -Duser.dir=/Users/huahua为例
但是目录下根本没有这个文件啊,如果相对路径再复杂一点,直接就出问题了
public class FileUtils {
public static void main(String[] args) {
File file = new File("./go");
System.out.println(file.exists());
System.out.println(file.getAbsolutePath());
Arrays.stream(file.listFiles()).forEach(p -> System.out.println(p.getAbsolutePath()));
// Arrays.stream(file.listFiles()).forEach(p -> System.out.println(p.getPath()));
// Arrays.stream(file.list()).forEach(System.out::println);
// System.out.println(file.getAbsolutePath());
}
}
得出结果
那么真实的路径是
真实路径与没有设置user.dir的情况一样。
这个为啥影响绝对路径呢,因为很可能因为路径问题导致生产事故。
原理
根据上面的实际测试,相对路径是相对当前user.dir而言的,那么绝对路径呢
userDir
private static final String USER_DIR = initProperty("user.dir");
private static String initProperty(String key) {
String v = System.getProperty(key);
if (v == null) {
throw new InternalError("null property: " + key);
}
return v;
}
那么真实的user.dir是,不设置VM -Duser.dir参数
可以看出实际上,user.dir真实为当前的根路径,设置-Duser.dir并不会影响实际的文件路径,但是AbsolutePath就会不一致
那么使用绝对路径new File呢
public String resolve(File f) {
if (isAbsolute(f)) return f.getPath();
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPropertyAccess("user.dir");
}
return resolve(userDir, f.getPath());
}
if (isAbsolute(f)) return f.getPath();
如果是绝对路径不再拼接,所以绝对路径是绝对准确的,相对路径就会出问题。
总结
不知道为什么File的AbsolutePath要取系统变量,而实际文件的地址却是另外的地址,这很容易导致文件路径不对,导致读取不到。关键在于读取绝对路径使用user.dir但是文件的真实路径与绝对路径不对应。