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

java中的相对路径和绝对路径以及一些引申

2017-03-21 20:17 267 查看

1-问题:

onos开发中,自己定义了一个json文件,用于存放openflowip和netconf deviceid 的映射关系,在启动sptnConfigProvider阶段去启动这个配置文件读取。部分人使用的项目因为不在home目录下造成了该配置文件的绝对路径无法读取,形成onos启动阶段的文件读取异常打印!

2-处理过程

2.1 设置相对路径处理====》失败

将new file中传入的路径字符串改成相对路径,但是在实际运行时候仍然无法找到;

原因:脱离了项目开发环境,在命令行下运行,相对路径失效;

=========》脱离了IDE环境该写法是错误的;

2.2 获取CLASSPATH下文件的绝对路径====》失败

使用网上的方法获取路径,尝试代码如下:

private static String cp = "/com/lavasoft/cfg/syscfg.properties";
//当前类的绝对路径
System.out.println(Test.class.getResource("/").getFile());
//指定CLASSPATH文件的绝对路径
System.out.println(Test.class.getResource(cp).getFile());
//指定CLASSPATH文件的绝对路径
File f = new File(Test.class.getResource(cp).getFile());
System.out.println(f.getPath());


IDE环境可以找到一个较为准确的路径,但是实际调用过程中是在jar包中调用及运行,此情况下则返回失败;

2.3 用户目录结合CLASSPATH获取====》失败

默认情况下,Java.io 包中的类总是根据当前用户目录来分析相对路径名。此目录由系统属性 user.dir指定,通常是Java 虚拟机的调用目录.”

//获取用户的当前工作目录
System.out.println("sysytem usrdir====>" + System.getProperty("user.dir"));
//获取当前运行程序的完整路径,绝对的路径,并且适应操作系统,
System.out.println("sysytem classpath====>" + System.getProperty("java.class.path"));


onos由karaf启动,得到的当前用户工作目录并不是指定代码存放目录;

获取的java.class.path在onos运行环境则是由许多个库组成,此种方法无法得到正确结果!

2.4 以流方式获取jar包,读取json流====》成功

最终处理方式,采用绝对路径和相对路径同时生效的方式进行处理,默认情况下从jar包中以文件流的形式读入json文件,但是配置相关命令行,同时支持切换为输入指定路径或只用默认路径(均为绝对路径的方式来处理文件)

if (!absluteFlag) {
String path = relativePath;
InputStream input = getClass().getClassLoader().getResourceAsStream(path);
rootNode = mapper.readTree(input);
} else {
String path = abslutePath;
rootNode = mapper.readTree(new File(path));
}


3-总结-java路径获取及file

根据上述尝试,可以大致将java代码中获取代码目录的方法总结如下:

1、使用相对路径处理(适用于IDE开发软件,不适用于jar包类型调用)

2、使用System.getProperty(“user.dir”));找到用户目录(适用于库文件存放在系统用户目录的情况)

3、使用CLASSPATH

Class.class.getClass().getResource(“/”).getPath();在IDE开发软件可用,如果为jar包则无法找到,返回空;

4、使用getClassLoader找到调用jar路径

this.getClass().getClassLoader().getResource(“.”).toString();

getResource(“.”)无法找到,但是若为一个jar包存在的文件名,则可以找到

window实验代码:

import java.io.File;

import java.io.IOException;

public class FileTestF
afac
wding {

import java.io.File;
import java.io.IOException;
public class FileTestFwding {
public void getClassTest() {
//getClass  getClass().getResource() 方法获得相对路径( 此方法在jar包中无效。返回的内容最后包含/)
String path1 = Class.class.getClass().getResource("/").getPath();
System.out.println("Class.class.getClass()====>" + path1);
String path2 = this.getClass().getResource("/").getPath();
System.out.println("getClass()====>" + path2);

//取得根目录路径
String rootPath=getClass().getResource("/").getFile().toString();
//当前目录路径
String currentPath1=getClass().getResource(".").getFile().toString();
String currentPath2=getClass().getResource("").getFile().toString();
//当前目录的上级目录路径
String parentPath;
parentPath=null;
//以下步骤无法运行在getResource("../")就返回失败
//parentPath = getClass().getResource("../").getFile().toString();
System.out.println("根目录:" + rootPath + "====当前目录:" + currentPath1 + "====上级目录:" + (parentPath==null ? "error path!!":parentPath));

//getClassLoader
String path3 = this.getClass().getClassLoader().getResource(".").toString();
System.out.println("getClassLoader====>" + path3);
}

public static void main(String[] args) throws IOException {
File file = new File(".");
//file相对路径
System.out.println("File getPath====>" + file.getPath());
//file标准路径
System.out.println("File getCanonicalPath====>" + file.getCanonicalPath());
//file绝对路径
System.out.println("File getAbsolutePath====>" + file.getAbsolutePath());

//获取用户的当前工作目录
System.out.println("sysytem usrdir====>" + System.getProperty("user.dir"));
//获取当前运行程序的完整路径,绝对的路径,并且适应操作系统,
System.out.println("sysytem classpath====>" + System.getProperty("java.class.path"));
//java安装目录
System.out.println("sysytem java安装目录====>" + System.getProperty("java.home"));
FileTestFwding fwdingtest = new FileTestFwding();
fwdingtest.getClassTest();

}

}


​ windows运行结果:

File getPath====>.
File getCanonicalPath====>E:\0001_JAVA_TEST_FWDING
File getAbsolutePath====>E:\0001_JAVA_TEST_FWDING\.
sysytem usrdir====>E:\0001_JAVA_TEST_FWDING
sysytem classpath====>E:\0001_JAVA_TEST_FWDING\bin
sysytem java安装目录====>D:\Program Files\Java\jdk1.8.0_45\jre
Class.class.getClass()====>/E:/0001_JAVA_TEST_FWDING/bin/
getClass()====>/E:/0001_JAVA_TEST_FWDING/bin/
根目录:/E:/0001_JAVA_TEST_FWDING/bin/====当前目录:/E:/0001_JAVA_TEST_FWDING/bin/====上级目录:error path!!
getClassLoader====>file:/E:/0001_JAVA_TEST_FWDING/bin/


linux idea JUNIT测试运行结果

File getPath====>.

File getCanonicalPath====>/home/ubuntu/CBB_2.0/south/provider/netconf

File getAbsolutePath====>/home/ubuntu/CBB_2.0/south/provider/netconf/.

sysytem usrdir====>/home/ubuntu/CBB_2.0/south/provider/netconf

sysytem classpath====>很多个jar包,不一一列出

sysytem java安装目录====>/usr/lib/jvm/java-8-oracle/jre

Class.class.getClass()====>/home/ubuntu/CBB_2.0/south/provider/netconf/target/test-classes/

getClass()====>/home/ubuntu/CBB_2.0/south/provider/netconf/target/test-classes/

getClassLoader====>file:/home/ubuntu/CBB_2.0/south/provider/netconf/target/test-classes/


onos jar包运行模式:

File getPath====>.
File getAbsolutePath====>/home/ubuntu/Applications/apache-karaf-3.0.8/.
sysytem usrdir====>/home/ubuntu/Applications/apache-karaf-3.0.8
sysytem classpath====>/home/ubuntu/Applications/apache-karaf-3.0.8/lib/karaf-jaas-boot.jar:/home/ubuntu/Applications/apache-karaf-3.0.8/lib/karaf-org.osgi.core.jar:/home/ubuntu/Applications/apache-karaf-3.0.8/lib/karaf.jar
sysytem java安装目录====>/usr/lib/jvm/java-8-oracle/jre
getClassLoader====>bundle://205.0:1/netconf_openflow-cfg.json
Error executing command: java.lang.NullPointerException
onos>


getClass().getResource(“.”).getFile().toString(); 方式在IDEA环境可以运行,但是如果类似onos适用jar包的话,则无法会报空指针;

this.getClass().getClassLoader().getResource(“.”).toString();在IDEA环境返回执行bin路径,但是jar包模式在“.”情况无法返回当前目录,加入getResource入参为jar包中包含的一个文件资源,则可以返回一个jar包的路径 //205.0:1/netconf_openflow-cfg.json;其已经以文件流方式存放于jar包,可以采用getResourceAsStream方法,以inputStream方式处理需要处理的文本文件;

4-引申-Java File文件流

4.1 概念

装饰器模式

在java中把不同的输入 \ 输出源(键盘、文件、网络连接等)抽象表述为流(stream),通过流的方式允许java程序使用相同的方式来访问不同的输入、输出源。STREAM从源SOURCE到接收SINK的有序数据。

流的方向:

输入流:只能从中读取数据,而不能向其写入数据;====》InputStream\Reader

输出流:只能向其写入数据,而不能从中读取数据;====》OutputStream\Writer

流的格式:

字节流:字节流操作的数据单元是8位的字节====》以Reader和Writer为基类;

字符流:字符流操作的数据单元是16位的字符====》以InputStream和OutputStream为基类;

流的角色:

节点流:从/向特定IO设备(如磁盘、网络)读、写数据的流

处理流:对一个已存在的流进行连接和封装后的流来实现数据读写功能;

如果进行输入输出的内容是文本内容则应该考虑使用字符流;

如果进行输入输出的内容是二进制内容则考虑使用字节流;

4.2 引申-对象序列化

对象序列化的目标是将对象保存到磁盘上,或允许在网络中直接传输对象。

允许把内存中的java对象转换成平台无关的二进制流,从而允许这种二进制流持久地保存在磁盘上,通过网络将二进制流传输到另一个网络节点。

4.3 区别总结

①File类封装了对用户机器的文件系统进行操作的功能。例如,可以用File类获得文件上次修改的时间移动,或者对文件进行删除、重命名。

②File类与FileInputStream类的区别:

流类关注的是文件内容,而File类关注的是文件在磁盘上的存储。

File不属于文件流,只能代表一个文件或是目录的路径名而已。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: