谈谈Java开发中遇到的资源文件路径问题(一)

在Java开发中,往往我们需要读取配置文件,或者读写系统文件,读写下载文件等等操作,是不是有时遇到提示系统找不到指定路径的文件的错误,

由此,我今天整理一下,希望以后能避免这种错误的出现。

面对路径问题,我们总得问问自己,什么是绝对路径,什么是相对路径,相对路径又是相对于谁,以谁作为参考点?

所谓的绝对路径,就是文件在整个文件系统的全路径,如在Windows下,D:\JAVA\MyEclipse\MyEclipse 10 这个文件夹 或者 D:\JAVA\MyEclipse\MyEclipse 10\myeclipse.exe

这个文件,都是以全路径名的形式出现的。只是在Java代码中,\  是必须转义的,所以我们写绝对路径时,总会D:\\JAVA\MyEclipse\\MyEclipse 10\\myeclipse.exe。

如代码中:

File file04 = new File("C:\\test1\\test101\\SeProjectFileDemo04.txt");

File file05 = new File(dirAbsPath05,"SeProjectFileDemo05.txt");

这两种都是绝对路径的写法,其中前者中C:\\test1\\test101\\的目录必须事先已经存在者两个目录,

后者dirAbsPath05也必须是已经创建好的目录,如代码中就

File dir05 = new File("C:\\test2\\test201");
if(!dir05.exists()) dir05.mkdirs();

创建好这两个目录啦。


那什么什么是相对路径呢?

所谓的相对路径,就是相对某个目录的情况下,某个资源文件的短名称,这其中就涉及到参考谁的问题了。

如:如果我说,以后你们写相对路径,都是以 D:\\JAVA\MyEclipse\\MyEclipse 10 这个目录为参考点 ,那么 

File file = new File("myeclipse.exe");   中的"myeclipse.exe" 就是一个相对路径的写法。


那么在开发Java程序的时候,写相对路径时,这个参考点会是那么目录呢?这个等看完相应的代码就知道了。


首先说的是JavaSe的应用程序工程:

首先我创建了一个JavaApplication工程,工程根目录是:D:\JAVA\MyEclipse10\ThreeDays ,大家暂时记住这个路径

然后我新建一个普通Java类 :ThreeDays/src/three/day/filepath/FilePathDemo01.java 

代码如下:

package three.day.filepath;

import java.io.File;
import java.io.IOException;

public class FilePathDemo01 {

public static void main(String[] args) throws IOException {
//-------------------------------使用相对路径----------------------------//
File file01 = new File("SeProjectFileDemo01.txt");
if(!file01.exists()) file01.createNewFile();
String fileAbsPath01 = file01.getAbsolutePath();
System.out.println(fileAbsPath01);

File file02 = new File("/", "SeProjectFileDemo02.txt");
if(!file02.exists()) file02.createNewFile();
String fileAbsPath02 = file02.getAbsolutePath();
System.out.println(fileAbsPath02);

File file03 = new File("dir", "SeProjectFileDemo03.txt");
if(!file03.exists()) file03.createNewFile();
String fileAbsPath03 = file03.getAbsolutePath();
System.out.println(fileAbsPath03);
//--------------------------------使用绝对路径----------------------------//
//创建的文件不再工程目录下
//自己手动在C盘下建好test1和test101文件夹
File file04 = new File("C:\\test1\\test101\\SeProjectFileDemo04.txt");
if(!file04.exists()){
file04.createNewFile();
}
String fileAbsPath04 = file04.getAbsolutePath();
System.out.println(fileAbsPath04);

//使用代码创建目录
File dir05 = new File("C:\\test2\\test201");
if(!dir05.exists()) dir05.mkdirs();
String dirAbsPath05 =  dir05.getAbsolutePath();
System.out.println(dirAbsPath05);
//在创建好的目录创建文件
File file05 = new File(dirAbsPath05,"SeProjectFileDemo05.txt");
if(!file05.exists()){
file05.createNewFile();
}
String fileAbsPath05 = file05.getAbsolutePath();
System.out.println(fileAbsPath05);
}
}


运行效果为:

D:\JAVA\MyEclipse10\ThreeDays\SeProjectFileDemo01.txt
D:\SeProjectFileDemo02.txt
D:\JAVA\MyEclipse10\ThreeDays\dir\SeProjectFileDemo03.txt
C:\test1\test101\SeProjectFileDemo04.txt
C:\test2\test201
C:\test2\test201\SeProjectFileDemo05.txt


涉及绝对的代码,没什么好说的了,都写死的了。但是相对路径话,我们通过观察,可以总结:

在JavaSe工程中,相对路径的参考点就是 工程的根目录,我代码工程目录一开始就提到是 

D:\JAVA\MyEclipse10\ThreeDays

所以,运行效果的第一和第三行,就很正常不过了。

可是,有没有发现第二行的输出结果,竟然是D:\SeProjectFileDemo02.txt,我们的工程根目录不是D:\JAVA\MyEclipse10\ThreeDays吗?

看看代码写法:File file02 = new File("/", "SeProjectFileDemo02.txt");

由此,可以看出,当父目录是 / 时,就代表工程根目录的根目录咯。


接下来,再看看通过类装载器获取资源文件时,相对路径的参考点又是那个目录呢?

工程还是原来的工程,工程根目录:D:\JAVA\MyEclipse10\ThreeDays

类是:/ThreeDays/src/three/day/filepath/FilePathDemo02.java

其中,代码是通过类装载器去读取资源文件的。

配置文件dbcfg.properties的内容就三行数据:

url=jdbc:mysql://localhost:3306/test
user=root
password=916520


package three.day.filepath;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class FilePathDemo02 {
public static void main(String[] args) throws IOException {

/**
* 1、一开始,假设相对目录的参考点 是 工程的根目录
* 1)然后将dbcfg.properties配置文件放在工程根目录下,可是运行出错,说明通过类装载器去读取相对路径文件时,相对路径的参考点不是工程根目录
* 2、假设,工程下的bin目录是相对路径的参考点,将dbcfg.properties配置文件放在bin目录下,运行,果真可以,假设成立
* 3、假设,如果dbcfg.properties配置文件放在bin目录下的three/day/目录下,相对路径还是这样写"dbcfg.properties",
* ClassLoader会不会帮我深度搜索呢?运行,报错,证明ClassLoader不会帮我们搜索,只好改成three/day/dbcfg.properties
*/

// three/day/dbcfg.properties
// three/day/filepath/dbcfg.properties
// dbcfg.properties
loaderFindFile("dbcfg.properties");
}
private static void loaderFindFile(String relativePath) throws IOException {
ClassLoader loader = FilePathDemo02.class.getClassLoader();
System.out.println(loader);
InputStream is = loader.getResourceAsStream(relativePath);
Properties props = new Properties();
props.load(is);
String url = props.getProperty("url");
String user = props.getProperty("user");
String password = props.getProperty("password");
System.out.println(url);
System.out.println(user);
System.out.println(password);
}
}


小细节:我在代码中说,将dbcfg.properties配置文件放在bin目录下,其实我只是把配置文件放置在 src 目录下即可。

因为,继承开发环境,实际src中参与编译的文件生成的文件 放置在对应的bin目录下。


另外,补充一点,修改源代码成这样:

package three.day.filepath;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Properties;

public class FilePathDemo03 {
public static void main(String[] args) throws IOException, URISyntaxException {
loaderFindFile("dbcfg.properties");
}

private static void loaderFindFile(String relativePath) throws IOException, URISyntaxException {
ClassLoader loader = FilePathDemo03.class.getClassLoader();
URL u = loader.getResource(relativePath);
File file = new File(u.getPath());
System.out.println(u.getPath());
// File file = new File(u.toURI());
// System.out.println(u.toURI().getPath());
FileInputStream fis = new FileInputStream(file);
Properties props = new Properties();
props.load(fis);
String url = props.getProperty("url");
String user = props.getProperty("user");
String password = props.getProperty("password");
System.out.println(url);
System.out.println(user);
System.out.println(password);
}
}

为什么要这样改呢?

原来是:

ClassLoader loader = FilePathDemo02.class.getClassLoader();
InputStream is = loader.getResourceAsStream(relativePath);

改成:

ClassLoader loader = FilePathDemo03.class.getClassLoader();
URL u = loader.getResource(relativePath);
File file = new File(u.getPath());
FileInputStream fis = new FileInputStream(file);

为什么需要这样的改变呢?

第一种的做法,是通过类装载器装载配置文件,类装载器只会读取一遍配置文件,之后配置文件的内容一致驻留在内存中,

可是如果我们是做web开发的话,web服务器启动了,你要修改配置文件的里面,如果使用第一种方式的话,你想想,

会不会立刻修改,立刻生效呢?不会!除非你把web服务重启,或者重新部署web应用。可是一旦产品上线,一般不允许

这种操作的。所以你必须使用第二中写法了,这样,还是读取文件,每次都会来读取配置文件,这样,你没修改了配置文件

就会立刻生效,因为再次读取文件,当然也就是更新后的内容了。


下面再谈谈开发web应用的相对路径问题,内容太多了,还是写在 谈谈Java开发中遇到的资源文件路径问题(二)吧!







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值