onos开发中,自己定义了一个json文件,用于存放openflowip和netconf deviceid 的映射关系,在启动sptnConfigProvider阶段去启动这个配置文件读取。部分人使用的项目因为不在home目录下造成了该配置文件的绝对路径无法读取,形成onos启动阶段的文件读取异常打印!
将new file中传入的路径字符串改成相对路径,但是在实际运行时候仍然无法找到;
原因:脱离了项目开发环境,在命令行下运行,相对路径失效;
=========》脱离了IDE环境该写法是错误的;
使用网上的方法获取路径,尝试代码如下:
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包中调用及运行,此情况下则返回失败;
默认情况下,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运行环境则是由许多个库组成,此种方法无法得到正确结果!
最终处理方式,采用绝对路径和相对路径同时生效的方式进行处理,默认情况下从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));
}
根据上述尝试,可以大致将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 FileTestFwding {
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>
在java中把不同的输入 \ 输出源(键盘、文件、网络连接等)抽象表述为流(stream),通过流的方式允许java程序使用相同的方式来访问不同的输入、输出源。STREAM从源SOURCE到接收SINK的有序数据。
流的方向:
流的格式:
流的角色:
如果进行输入输出的内容是文本内容则应该考虑使用字符流;
如果进行输入输出的内容是二进制内容则考虑使用字节流;
对象序列化的目标是将对象保存到磁盘上,或允许在网络中直接传输对象。
允许把内存中的java对象转换成平台无关的二进制流,从而允许这种二进制流持久地保存在磁盘上,通过网络将二进制流传输到另一个网络节点。
①File类封装了对用户机器的文件系统进行操作的功能。例如,可以用File类获得文件上次修改的时间移动,或者对文件进行删除、重命名。
②File类与FileInputStream类的区别:
流类关注的是文件内容,而File类关注的是文件在磁盘上的存储。
File不属于文件流,只能代表一个文件或是目录的路径名而已。