java不同路径读取文件的方式--Thread.currentThread().getContextClassLoader(), Test.class.getClassLoader()等

Java code

?

1

2

3

4

5

6

7

8

9

10

11

public class Test {

    public static void main(String[] args) {

         

        // 此时三个ClassLoader是同一个对象

        System.out.println(Thread.currentThread().getContextClassLoader()); // 当前线程的类加载器

        System.out.println(Test.class.getClassLoader()); // 当前类的类加载器

        System.out.println(ClassLoader.getSystemClassLoader()); // 系统初始的类加载器

         

    }

}


如果楼主了解过openfire应该对ClassLoader有比较深的理解。
打个简单的比方,你一个WEB程序,发布到Tomcat里面运行。
首先是执行Tomcat org.apache.catalina.startup.Bootstrap类,这时候的类加载器是ClassLoader.getSystemClassLoader()。
而我们后面的WEB程序,里面的jar、resources都是由Tomcat内部来加载的,所以你在代码中动态加载jar、资源文件的时候,首先应该是使用Thread.currentThread().getContextClassLoader()。如果你使用Test.class.getClassLoader(),可能会导致和当前线程所运行的类加载器不一致(因为Java天生的多线程)。
Test.class.getClassLoader()一般用在getResource,因为你想要获取某个资源文件的时候,这个资源文件的位置是相对固定的。

java的类加载机制(jvm规范)是委托模型,简单的说,如果一个类加载器想要加载一个类,首先它会委托给它的parent去加载,如果它的所有parent都没有成功的加载那么它才会自己亲自来,有点儿像儿子使唤老子的感觉。。jvm也拼爹啊,,,,,
在jvm中默认有三类loaer,bootstrap,ext,app,其中boot最大是爷爷,app最小是孙子,ext中间是爹。
它们有权限访问的classpath也不一样,boot是jdk或jre下面的lib目录,ext是jdk或jre的ext目录,而app是由用户指定的路径,比如用-cp参数指定的目录或jar。他们没有权力访问其他人的classpath,这样问题就来鸟,,,,可能有人会问狗司令大人闲得蛋疼啊,搞这么复杂,据说是为了安全考虑,避免用户的恶心意代码侵蚀jvm,,问题就是当bootstrap或ext想要加载用户指定classpath中的类就会失败,因为这俩货没有权限访问团app路径中的类的,,所以就搞了这么一个不伦不类的contextloader。。。。

读取文件的写法,相对路径
在当前的目录结构中读取test.txt的有四种写法

简单粗暴的 File file = new File(“src/test.txt”)
使用类的相对路径
使用当前线程的类加载器
读取web工程下的文件 使用getRealPath()读取


 File file = new File("src/test.txt");
 File file = new File(TestRelativePath.class.getResource("/test.txt").getFile());
  File file = new File(Thread.currentThread().getContextClassLoader().getResource("test.txt").getFile());
   File file = new File(getServletContext().getRealPath("/WEB-INF/classes/test.txt"));

下面我来一一介绍:

简单粗暴的 File file = new File(“src/test.txt”);
  @Test
    /**
     * 这种方法 “” 空代表的是 这个Java项目 TestSomeTechnology  由于实际项目在打包后没有src目录 所以这种方法不常用
     */
    public  void  testMethod1() throws IOException{
        File file = new File("src/test.txt");
        BufferedReader br = new BufferedReader(new FileReader(file));
        String len = null;
        while ((len=br.readLine())!=null){
            System.out.println(len);
        }
    }
使用类的相对路径
TestRelativePath.class.getResource(“/test.txt”).getFile()

 @Test
    /**
     * 使用类的相对路径
     * 这种方法 “/” 代表的是bin  src文件夹和resources 文件夹下的的东西都会被加载到bin下面 因为这两个文件被配置为了source
     */
    public  void  testMethod2() throws IOException{

        File file = new File(TestRelativePath.class.getResource("/test.txt").getFile());
        BufferedReader br = new BufferedReader(new FileReader(file));
        String len = null;
        while ((len=br.readLine())!=null){
            System.out.println(len);
        }
    }
使用当前线程的类加载器
Thread.currentThread().getContextClassLoader().getResource(“test.txt”).getFile()

 @Test
    /**
     * 这种是通过当前线程的类加载器
     * 这种方法 “ ” 空代表的是bin  于是就直接填写test 文件夹下的的东西都会被加载到bin下面 因为这两个文件被配置为了source
     */
    public  void  testMethod3() throws IOException{

        File file = new File(Thread.currentThread().getContextClassLoader().getResource("test.txt").getFile());
        BufferedReader br = new BufferedReader(new FileReader(file));
        String len = null;
        if ((len=br.readLine())!=null){
            System.out.println(len);
        }
    }

读取web工程下的文件 使用getRealPath()读取
目录如下 


读取 index.jsp

@WebServlet(name = "TestServlet",urlPatterns = "/TestServlet")
public class TestServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
    }

    /**
     *  web工程的根目录是 webRoot 使用 “/” 代表webroot webroot下面有index.jsp文件
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        File file = new File(getServletContext().getRealPath("/index.jsp"));
        BufferedReader br = new BufferedReader(new FileReader(file));
        String len = null;
        while ((len=br.readLine())!=null){
            System.out.println(len);
        }
    }
}
读取 test.txt文件 
不过如果想读取test.txt 的话 我们可用用上面的方式

 File file = new File(Thread.currentThread().getContextClassLoader().getResource("test.txt").getFile());
1
也可以使用 getRealPath() 
不过由于是以 webroot为根目录 我们需要从classes里面读

 File file = new File(getServletContext().getRealPath("/WEB-INF/classes/test.txt"));
1
getResourceAsStream()方法详解
getResourceAsStream()用法与getResouce()方法一样的,用getResource()取得File文件后,再new FileInputStream(file) 与 getResourceAsStream() 的效果一样。。

给出示例 
两个代码效果一样

        InputStream inputStream1 = new FileInputStream(new File(Thread.currentThread().getContextClassLoader().getResource("test.txt").getFile()));
//=============================
        InputStream inputStream2 = Thread.currentThread().getContextClassLoader().getResourceAsStream("test.txt");
--------------------- 
作者:guxiangfly 
来源:CSDN 
原文:https://blog.csdn.net/my__sun_/article/details/74450241 
版权声明:本文为博主原创文章,转载请附上博文链接!

猜你喜欢

转载自blog.csdn.net/weixin_38610651/article/details/85990857