项目中不同位置资源文件读取的几种方式

项目工程下读取文件的几种方式。

【1】图片在src目录下,即资源文件;

项目中不同位置资源文件读取的几种方式_第1张图片

此时测试类与图片位置无关。

InputStream inputStream = getClass().getClassLoader().getResourceAsStream("getTclazz.jpg");
//使用getClassLoader,不加 /

 InputStream inputStream = getClass().getResourceAsStream("/getTclazz.jpg");
//这里需要加 /  

【2】图片在dao目录下

项目中不同位置资源文件读取的几种方式_第2张图片

① 如果测试类不在该目录下-与文件不同目录

项目完整路径:

 InputStream inputStream = 
 getClass().getClassLoader().getResourceAsStream("com/jdbc/dao/getTclazz.jpg");
 
 /*不要加 / , /com/jdbc/dao/getTclazz.jpg 错误!\--*/
-------------------------------------------------------
InputStream inputStream = getClass().getResourceAsStream("/com/jdbc/dao/getTclazz.jpg");
// 要加 /

② 如果测试类在该目录下-与文件同一目录

调用的java类文件在该包下,【如测试类和文件都在com.jdbc.dao包下】则可使用:

InputStream inputStream = getClass().getResourceAsStream("getTclazz.jpg");

//如果不加 / ,则相对的是该类所在的位置

【3】分析

1)getClass().getResourceAsStream(“getTclazz.jpg”);

​2)getClass().getResourceAsStream("/com/jdbc/dao/getTclazz.jpg");

3)getClass().getClassLoader().getResourceAsStream(“com/jdbc/dao/getTclazz.jpg”);

第一种和第二种方式是采用Class对象去加载,第三种采用ClassLoader对象去加载资源文件,之所以Class对象也可以加载资源文件是因为Class类封装的ClassLoader的getResourceAsStream方法。

从Class类中的源码中可以看出:

public InputStream getResourceAsStream(String name) {
	//这里有名字解析操作
        name = resolveName(name);
        ClassLoader cl = getClassLoader0();
        if (cl==null) {
            // A system class.
            return ClassLoader.getSystemResourceAsStream(name);
        }
        return cl.getResourceAsStream(name);
    }

resolveName方法源码如下:

    /**
     * Add a package name prefix if the name is not absolute 
     * Remove leading "/" if name is absolute
     */
    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;
    }

即,如果name是绝对路径(带有/)那么就移除/然后使用classloader.getResourceAsStream(name)来获取流。

如果name是相对路径(不带有/),那么就添加包前缀,然后使用classloader.getResourceAsStream(name)来获取流。

ClassLoader.getResourceAsStream()方法如下:

//不会再次解析name
public InputStream getResourceAsStream(String name) {
        URL url = getResource(name);
        try {
            return url != null ? url.openStream() : null;
        } catch (IOException e) {
            return null;
        }
    }

最终都会走到ClassLoader.getResource()方法:

public URL getResource(String name) {
        URL url;
        if (parent != null) {
            url = parent.getResource(name);
        } else {
     	   // 使用该方法加载资源
            url = getBootstrapResource(name);
        }
        if (url == null) {
            url = findResource(name);
        }
        return url;
    }

解释如下

  1. 第三种是最本质的做法,前两种也是基于第三种去实现的。JVM会使BootstrapLoader去加载资源文件。所以路径还是这种相对于类根目录

  2. 第一种方式将给资源文件添加当前类的包名作为路径使用BootstrapLoader加载。

  3. 第二种方式资源文件拥有/,则直接使用 / 后面的部分作为路径去加载资源文件。


如下,当文件在src根目录下时,使用三种方式读取的结果:

如果文件与测试类在同一包下,第一个方式可以读取,其他两种不可以。

项目中不同位置资源文件读取的几种方式_第3张图片


【4】图片在项目路径下-contextPath 下

项目中不同位置资源文件读取的几种方式_第4张图片

相对路径:

InputStream inputStream = new FileInputStream("getTclazz.jpg");

绝对路径:

InputStream inputStream = new FileInputStream("C:\\Users\\12746\\Workspaces\\MyEclipse 8.5\\firstJDBCPro2\\getTclazz.jpg");

【5】不同路径的获取

① 获取当前类路径

/C:/Users/12746/Workspaces/MyEclipse%208.5/Spring-2/WebRoot/WEB-INF/classes/com/web/test/

path = this.getClass().getResource("").getPath();

即,getResourceAsSteam获取的是classes中的文件(项目结构图中的src下)。


② 获取项目根路径

/*  获取工程根目录C:\Users\12746\Workspaces\MyEclipse 8.5\Spring-2 */
path = System.getProperty("user.dir");

③ 获取类加载路径

1. / 表示相对于src目录;
2. getClassLoader()只能使用相对路径

path = this.getClass().getResource("/").getPath();
/*/C:/Users/12746/Workspaces/MyEclipse%208.5/Spring-2/WebRoot/WEB-INF/classes/*/
path = this.getClass().getClassLoader().getResource("").getPath();

以上举例,文件在src或项目下,并没有在WebRoot下。如果文件在WebRoot下,请使用ServletContext获取。

【6】读取classpath下的json文件并返回JSONObject

这里使用的是fastJSON,源码实例如下:

  /**
     * 读取json文件并解析为JSONObject
     * @param path--文件保存在classpath下的全路径 如test.json
     */
    public static JSONObject readerJSON (String path) throws Exception {

        try {
            if (!path.startsWith("/")&&!path.startsWith("\\")){
                path="/"+path;
            }
            InputStream inputStream = ReaderJSONUtil.class.getResourceAsStream(path);
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream,"UTF-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            StringBuffer jsonBuffer = new StringBuffer();
            String line=null;
            while ((line=bufferedReader.readLine())!=null){
                jsonBuffer.append(line);
                log.debug(line);
            }
            return JSON.parseObject(jsonBuffer.toString());

        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

你可能感兴趣的:(JavaSE-File)