• java中Class.getResourceAsStream()和ClassLoader.getResourceAsStream()的区别


    简介

    Class.getResourceAsStream()和ClassLoader.getResourceAsStream()方法都是从项目中读取文件,但很容易被搞混。

    ClassLoader

    public class Client2 {
    
      public static void main(String[] args) {
        //从classpath下查询
        InputStream in = Client2.class.getClassLoader().getResourceAsStream("files/asd.txt");
        if (in == null) {
          return;
        }
        try (BufferedReader br = new BufferedReader(new InputStreamReader(in))) {
          String line = null;
          while ((line = br.readLine()) != null) {
            System.out.println(line);
          }
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    
    }
    

    我们将文件放到classpath下,ClassLoader会直接从classpath的根目录下查找文件,
    输出结果为

    this is a test file2
    

    Class

    public class Client3 {
    
      public static void main(String[] args) {
        InputStream in = Client3.class.getResourceAsStream("/files/asd.txt");
        if (in == null) {
          return;
        }
        try (BufferedReader br = new BufferedReader(new InputStreamReader(in))) {
          String line = null;
          while ((line = br.readLine()) != null) {
            System.out.println(line);
          }
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    
    }
    

    通过Class也可以读到classpath下的文件,我们需要以/开头。

    public class Client4 {
    
      public static void main(String[] args) {
        InputStream in = Client4.class.getResourceAsStream("abc.txt");
        if (in == null) {
          return;
        }
        try (BufferedReader br = new BufferedReader(new InputStreamReader(in))) {
          String line = null;
          while ((line = br.readLine()) != null) {
            System.out.println(line);
          }
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    
    }
    

    我们将文件放到当前类所在的包下,这个时候不能以/开头,直接相对路径就可以。

    源码分析

    public final
        class Class<T> implements java.io.Serializable,
                                  java.lang.reflect.GenericDeclaration,
                                  java.lang.reflect.Type,
                                  java.lang.reflect.AnnotatedElement {
    	public InputStream getResourceAsStream(String name) {
            	name = resolveName(name);
            	ClassLoader cl = getClassLoader0();
            	if (cl==null) {
                		// A system class.
                		return ClassLoader.getSystemResourceAsStream(name);
            	}
       		//实际上还是调用ClassLoader的getResourceAsStream()方法
            	return cl.getResourceAsStream(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;
        }
    
    }
    

    总结

    ClassLoader从classpath下查询,不能以/开头,不能相对路径,Class如果以/开头,直接截取/之后的路径,不以/开头,转换成包含package的全路径,内部还是调用的ClassLoader的方法。

  • 相关阅读:
    跟着百度学PHP[6]超级全局变量
    DuBrute 3.1
    第三方提权之serv-u提权
    报错注入分析之Extractvalue分析
    报错注入分析之updatexml注入
    B/S与C/S架构
    Python IDLE背景设置与使用
    调试软件的基本方法
    Windows10下安装python(配置环境变量)
    磁盘分区
  • 原文地址:https://www.cnblogs.com/strongmore/p/14070524.html
Copyright © 2020-2023  润新知