您的位置:首页 > 编程语言 > Java开发

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

2013-10-06 00:40 701 查看
在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开发中遇到的资源文件路径问题(二)吧!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: