java读取文件的正确姿势

首先说明这篇博文只讲一个正确的方法。其他的给予工程目录读取文件的都是耍流氓。

这篇文章说的很清楚用工程目录作为基目录的不好

通过获取classpath路径:然后根据这个classpath路径读取资源文件

ClassLoader 提供了两个方法用于从装载的类路径中取得资源:

     直接从当前类路径也就是.class文件目录下读取资源文件,然后系统会自动将这个资源文件复制一份到.class文件目录下
    public URL  getResource (String name);  
    public InputStream  getResourceAsStream (String name);  

   这里name是资源的类路径,它是相对与“/”根路径下的位置。getResource得到的是一个URL对象来定位资源,而getResourceAsStream取得该资源输入流的引用保证程序可以从正确的位置抽取数据。
   但是真正使用的不是ClassLoader的这两个方法,而是Class的 getResource和getResourceAsStream方法,因为Class对象可以从你的类得到(如YourClass.class或 YourClass.getClass()),而ClassLoader则需要再调用一YourClass.class.getClassLoader()方法,不过根据JDK文档的说法,Class对象的这两个方法其实是“委托”(delegate)给装载它的ClassLoader来做的,所以只需要使用 Class对象的这两个方法就可以了。同时下面也可以看到他们的是有些下区别的。

因此,直接调用 this.getClass().getResourceAsStream(String name) ;获取流,静态化方法中则使ClassLoader.getSystemResourceAsStream (String name) ; 。

例子

1.System.out.println(SerialAndUnserial.class.getResource(“”).getFile());
得到的是当前类class文件的File目录。不包括自己类class文件在内。既是class文件的文件路径!
如:/home/cindy/eclipseworkspace/singleton_serial/bin/test/run/

2.System.out.println(SerialAndUnserial.class.getResource(“/”).getFile());
得到的是当前的classpath的绝对classpath路径 。这个是当前工程目录下bin目录的绝对地址。这个是平台无关性的地址。所以非常好。可以用它作为我们新建其他资源目录的基地址。
如:/home/cindy/eclipseworkspace/singleton_serial/bin/

classloader的例子

System.out.println(SerialAndUnserial.class.getClassLoader().getResource(“”).getFile());
得到的也是当前ClassPath的绝对URI路径 。这个刚好和class的getResource方法不一样。注意下
如: /home/cindy/eclipseworkspace/singleton_serial/bin/
System.out.println(“2\t” + SetTest.class.getClassLoader().getResource(“/”)); 输出 说空指针异常
java读取文件的正确姿势_第1张图片

一般我们是以classpath路径为基地址。然后和子地址合并成为一个新的最终的地址。
这里给出自己写的依据给出的子地址创建文件的例子。如果目录还没创建会自动创建。

package file.service;

import java.io.File;
import java.io.IOException;

import test.run.SerialAndUnserial;

public class FileService {

    public FileService() {
        // TODO Auto-generated constructor stub
    }

    public static File openFile(String filepath) {
        if (filepath == null || filepath == "") {
            return null;

        }
        String basePath = SerialAndUnserial.class.getResource("/").getFile();
        // 这里你可以看到classpath的地址在哪里
        System.out.println("classpath路径" + basePath);
        File file = null;

        /**
         * 有getCanonicalFile的效果是将含有的跳转到上层目录的../去掉。构成一个可以解析的目录
         * 形成这种形式/home/cindy/eclipseworkspace/singleton_serial/txt/object. txt
         * 在没有getCanonicalFile()方法调用前是这样的。
         * /home/cindy/eclipseworkspace/singleton_serial/../txt/object.txt
         * 你可以把那个方法去掉试下。貌似去掉也可以正常执行。
         */
        try {
            file = new File(basePath, filepath).getCanonicalFile();
        } catch (IOException e2) {
            // TODO Auto-generated catch block
            e2.printStackTrace();
        }

        try {
            System.out.println("该路径的父级目录" + file.getCanonicalPath());
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        // 判定这个抽象路径名表示的路径是否存在
        System.out.println(file.exists());
        if (!file.exists()) {
            // // 将所有缺少父级目录都创建好
            file.getParentFile().mkdirs();
            try {// 最后创建文件
                file.createNewFile();
                return file;
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        System.out.println(file.exists());
        return file;
    }

}

测试代码

String relativePath = "../txt/object.txt";  
File file = FileService.openFile(relativePath);
System.out.println(file.getPath());

输出结果
这里写图片描述

你可能感兴趣的:(java-8学习记录)