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

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 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> 
  • 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不属于文件流,只能代表一个文件或是目录的路径名而已。

猜你喜欢

转载自blog.csdn.net/xinquanv1/article/details/64499045