由于自己一知半解,所以在开发的过程中,涉及到Java文件路径的问题,在不同的系统中,不同IDE,不同的项目环境下,总是犯错误,每次通过百度搜索,动手实验,最终能够解决问题。但是,再下次遇到问题的时候,依然如故!而网络上的文章也是良莠不齐,复制粘贴,没有很好的梳理这个问题。所以,我自己想尝试把这个问题讲清楚。
一、开发环境
首先,我们要保持一致我们的开发环境,否则,一切都无从谈起。
1.操作系统:
在Windows中,路径分隔符是反斜杠 \ ,在Linux中,路径分隔符是斜杠 / 。
Linux是不支持反斜杠做路径分隔符。windows系统做了兼容,支持使用斜杠做路径分隔符。
如果使用File.separator,那么会根据当前运行程序的机器生成分隔符,这对于在windows上开发测试阶段是不适用的。
所以,我的经验是在开发中,全部用斜杠 / 做分隔符。
2. IDE:
Eclipse和IDEA中,对于相对路径的处理是不同的,我不想在IDE再劳神,所以开发中,一律使用绝对路径。这可以有效屏蔽IDE切换带来的风险,而且,使项目更健壮,对于项目迁移,外部环境,内部项目目录变换等等情况,都能更很好的适应这些变化。
3.项目环境:
这一块,其实就是屏蔽了外部环境影响之后,Java内部环境的细分了。暂时,可以分为两块:JavaSE,JavaWeb。我们下一部分开讲。
二、正文
我开发涉及到的目前就是JavaSE,JavaWeb两种环境下的路径的不同处理。
1.JavaSE环境下:
就是在普通的Java项目中:
1.1. 通过使用Java的类加载器来获取编译后类的根目录,然后,以此为基础,获取此目录下的自己想要的路径:
String path = this.getClass().getClassLoader().getResource("").getPath();
System.out.println(path);
注:此处的路径都是相对于类加载器的根目录而言的,所以,在getResource()方法的参数不能以斜杠开头。不过,这对于我们也没有什么影响,我们都是以此路径为基础,再后面继续使用的。
1.2.这种方法,其实是上面方法的变种,是通过当前类编译后的路径为基准,底层依然使用该类的类加载器:
//2.获取当前类的绝对路径
String path2 = this.getClass().getResource("").getPath();
System.out.println(path2);
//3.获取当前类的类加载器的根目录,与第一种方法效果相同
String path3 = this.getClass().getResource("/").getPath();
System.out.println(path3);
1.3.对上面的方法进一步延伸,我们直接找到类加载器,然后,去找绝对路径:
String path4 = ClassLoader.getSystemClassLoader().getResource("").getPath();
System.out.println(path4);
String path5 = ClassLoader.getSystemResource("").getPath();
System.out.println(path5);
1.4.这种方法,需要前置条件,就是要先有一个File的对象,获取到的项目的根路径,这与前面的方法的结果是不同的:
File file = new File("");
String canonicalPath = file.getCanonicalPath();
System.out.println(canonicalPath);
String absolutePath = file.getAbsolutePath();
System.out.println(absolutePath);
1.5.根据系统属性,获取项目的根路径:
String property = System.getProperty("user.dir");
System.out.println(property);
2.JavaWeb环境下:
通过使用ServletContext类对象来获取项目根目录的绝对路径:
ServletContext servletContext = this.getServletContext();
String realPath = servletContext.getRealPath("");
三、最佳实践
1. 路径分隔符统一使用斜杠;
2. 路径统一使用绝对路径;