JAVA获取路径问题

下午在公司纳凉,何同学突然问我,他的hadoop 有个java类如何获取在根目录的文本文件。

目录是这个样子的。

JavaPath 类 要读取文件夹testfolder的test.txt 文本。

写成绝对路径问题就解决了,也就是写成D://workspace/JavaPath/testfolder/test.txt 可是这个这个程序要打成jar包,放到服务器上执行,这时绝对路径就不灵了。

问题来了,就得想办法解决!

之前也没一直深入研究java路径的获取问题,不会了,咱们就百度呗,前辈们可定遇见过这样的问题。果然第一篇文件就是对java获取路径的总结:

1、JavaPath.class.getResource("") //得到的是当前类FileTest.class文件的URI目录。不包括自己!

结果:file:/D:/workspace/JavaPath/bin/cn/com/umesage/path/

2、JavaPath.class.getResource("/")得到的是当前的classpath的绝对URI路径。

结果:file:/D:/workspace/JavaPath/bin/

咱们来看看Class类的getResource 方法源码

public java.net.URL getResource(String name) {
        name = resolveName(name);//1
        ClassLoader cl = getClassLoader0();//2
        if (cl==null) {//3
            // A system class.
            return ClassLoader.getSystemResource(name);//4
        }
        return cl.getResource(name);//5
    }


一共 5行有效代码,咱们进入第一行,看看resoveName是如何实现的,废话不说上代码
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;
    }


这个方法逻辑是 如果输入的是“/” 那么就变成 “”  也就是 else 里面的代码, 如何输入的是“”  则if 为真 进入里面执行也就是把cn.com.umesage.path.JavaPath 中的点变成能让文件系统识别的cn/com/umesage/path/

接着看看getResource 方法的第二段代码,很遗憾是native 方法

// Package-private to allow ClassLoader access
    native ClassLoader getClassLoader0();


但是逻辑应该能看懂,意思是获取classloader,话外补充一下 类的加载器 ,此文不会深入讨论,只是初步介绍。
Java 中的类加载器大致可以分成两类,一类是系统提供的,另外一类则是由 Java 应用开发人员编写的。系统提供的类加载器主要有下面三个:
  • 引导类加载器(bootstrap class loader):它用来加载 Java 的核心库,是用原生代码来实现的,并不继承自 java.lang.ClassLoader
  • 扩展类加载器(extensions class loader):它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类。
  • 系统类加载器(system class loader):它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。可以通过ClassLoader.getSystemClassLoader()来获取它。

下面是一个示例,让大家了解一下这三种类加载器的使用场景

public class JavaClassLoader {

	public static void main(String[] args) {
		System.out.println(String.class.getClassLoader());// 引导类加载器
		ClassLoader loader = JavaPath.class.getClassLoader();
		while (loader != null) {
			System.out.println(loader.toString()); // 系统类加载器
			loader = loader.getParent(); // 扩展类加载器 ;JavaClassLoader的父类是Object类
		}

	}




上图是执行的结果

还是说了太多 和本篇无关的话.....

由之前的类加载器的介绍,就能知道getResource 方法中的第二行返回的不是null,因为它是由系统加载器加载的,所以跳到第五行。

第五行是return cl.getResource(name); 那么咱们进入 ClassLoader 的getResource 方法 源代码如下:

 // -- Resource --

    /**
     * Finds the resource with the given name.  A resource is some data
     * (images, audio, text, etc) that can be accessed by class code in a way
     * that is independent of the location of the code.
     *
     * <p> The name of a resource is a '<tt>/</tt>'-separated path name that
     * identifies the resource.
     *
     * <p> This method will first search the parent class loader for the
     * resource; if the parent is <tt>null</tt> the path of the class loader
     * built-in to the virtual machine is searched.  That failing, this method
     * will invoke {@link #findResource(String)} to find the resource.  </p>
     *
     * @param  name
     *         The resource name
     *
     * @return  A <tt>URL</tt> object for reading the resource, or
     *          <tt>null</tt> if the resource could not be found or the invoker
     *          doesn't have adequate  privileges to get the resource.
     *
     * @since  1.1
     */   
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;
    }


这段代码的注释 已解释的很清楚,就不再解释了,最后跟下去全是native 方式,有兴趣 可以继续研究JNI是如何实现的。

3.Thread.currentThread().getContextClassLoader().getResource("") //得到的也是当前ClassPath的绝对URI路径。

结果:file:/D:/workspace/JavaPath/bin/

4 JavaPath.class.getClassLoader().getResource("") //得到的也是当前ClassPath的绝对URI路径。

结果:file:/D:/workspace/JavaPath/bin/
5 ClassLoader.getSystemResource("")//得到的也是当前ClassPath的绝对URI路径。

结果:file:/D:/workspace/JavaPath/bin/
 对于何同学提出的文件相对路径 还是没有得到解决。

那么咱么就接着想办法。能不能通过绝对路径拼出个相对路径来

还好FIle 类 给咱们提供的获取当前路径的方法

File directory = new File("");//设定为当前文件夹// . 当前目录 ..是父目录,实现的代码如下

public class JavaPath {

	private final static String TEXT_URL = new java.io.File("").getAbsolutePath()+"/testfolder/test.txt";
	
	public static void main(String[] args) throws IOException {
		FileInputStream fis = new FileInputStream(new File(JavaPath.TEXT_URL));
		int word;
		while ((word=fis.read())!=-1) {
			System.out.print((char)word);
		}
		fis.close();
		
	}

}



问题总算解决了,希望可以帮助何同学运行起来。

关于FIle 类, 将在下篇文章详细介绍。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值