Class.getResourceAsStream() 和ClassLoader.getResourceAsStream()路径问题.md

Class.getResourceAsStream() 和ClassLoader.getResourceAsStream()路径问题

  1. 为什么要搞清楚这个东西。

    1. 在进行xml解析,获取xml文件流中
    2. 在获取properties文件流时
    3. 在获取其他文件的文件流时
  2. 两者的相对路径和绝对路径问题通过试验的方式得出结论

    /*编译后的class文件路径
    * |-src(com的上一级目录,名称和开发环境有关)
    	|----com
    	|-----|----xxx
    	|-----|-----|----test
    	|-----|-----|-----|----Test.class
    	|-----|-----|-----|----a.txt
    	|---a.xml
    	|---db.properties
    */
    //编译后文件的层次关系如上图所示
    
    
    
    //api中关于getResourceAsStream()的介绍,其方法本质时通过getResource()获取到url在封装成流
    //为了试验方便,则使用getResource()进行测试
    /*在委托前,使用下面的算法从给定的资源名构造一个绝对资源名: 
    
    	如果 name 以 '/' 开始 ('\u002f'),则绝对资源名是 '/' 后面的 name 的一部分。 
    	否则,绝对名具有以下形式: 
       		modified_package_name/name
    	其中 modified_package_name 是此对象的包名,该名用 '/' 取代了 '.' ('\u002e')。 
    	
    */
    
    
    package com.xxx.test;
    
    import java.net.URL;
    
    public class Test {
        public static void main(String[] args) {
            URL url = Test.class.getResource("a.txt");
            URL url1 = Test.class.getResource("/a.xml");
            URL url2 = Test.class.getClassLoader().getResource("db.properties");
            String path = url.getPath();
            String path1 = url1.getPath();
            String path2 = url2 .getPath();
            System.out.println("class.get..的相对路径位置:"+path);
            System.out.println("class.get..的绝对路径位置:"+path1);
            System.out.println("classloader.get..的相对路径位置:"+path2);
        }
    }
    /*
    结果:(其中ResourceAsStream为com包的上一级目录)
    class.get..的相对路径位置:
    					/C:/.../ResourceAsStream/com/xxx/test/a.txt
    class.get..的绝对路径位置:
    					/C:/.../ResourceAsStream/a.xml
    classloader.get..的相对路径位置:
    					/C:/.../ResourceAsStream/db.properties
    */
    /*
    分析:
    根据api描述,getResource()方法没有相对路径的概念,都是绝对路径,其根路径在src下
    
    如果是class.getResource()的名义向的相对路径(不带/)的:在原路径上加上该类的包名 即com/xxx/test/a.txt作为绝对路径。绝对路径的根就是src下的根ResourceAsStream/绝对路径
    
    如果是classLoader.getResource(“不带/+path”)方法,则默认把path作为绝对路径。和class.getResource("带/+path")相同。
    */
    //查看源码:
    public java.net.URL getResource(String name) {
        name = resolveName(name);
        ClassLoader cl = getClassLoader0();
        if (cl==null) {
            // A system class.
            return ClassLoader.getSystemResource(name);
        }
        return cl.getResource(name);
    }
    //class的getResource()方法线调用了resolveName方法进行路径的解析。在调用classLoader的getReSrouce(name)方法。
    
    private String resolveName(String name) {
        if (name == null) {
            return name;
        }
        if (!name.startsWith("/")) {
            Class<?> c = this;
            while (c.isArray()) {
                c = c.getComponentType();
            }
            String baseName = c.getName();
            int index = baseName.lastIndexOf('.');
            if (index != -1) {
                name = baseName.substring(0, index).replace('.', '/')
                    +"/"+name;
            }
        } else {
            name = name.substring(1);
        }
        return name;
    }
    //class的resolveName(String name)对name进行解析。可以发现,在有/的时候是调用了:
    //name.substring(1)把“/”去掉,再调用classLoader.getResource(String name)方法,与我们观察到的结果一致。
    //当没有“/”时会再name前面把包名的点“.”替换为"/"并作为路径加在name的前面作为绝对路径。
    
    //classLoader.getResource(String name) name值只能使用不带“/”的路径
    URL url4 = Test.class.getClassLoader().getResource("/db.properties");
    System.out.println(url4);//打印结果为null。找不到该路径。
    

    结论:

    1、getResourceAsStream(String name) 底层时调用了getResource()方法,两者的路径写法一致

    2、使用class的getResource(String name) 方法:

    ​ 1、如果以/开头+path 那么绝对路径为 包名上一级目录(这里是com的上一级目录)/+path;

    ​ 2、如果没有以/开头+path 那么绝对路径为 包名上一级目录/该类的包名路径(把包名的点替换为/)+“/”+path

    3、使用classLoader的getResource(String name) 方法:

    ​ 1、name中不能带有/

    ​ 2、路径为src(项目名)+“/”+name

    4、注意:路径关系是编译后的项目文件。不是在IDE中的开发目录下的路径

    ​ 比如在maven中开发目录下java下是包名+类名 resource下是资源文件

    ​ 在编译后是在target下的classes下有包文件以及资源文件

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值