介绍在java中的几种资源读取方式

来源:互联网 发布:手机淘宝店怎么注册 编辑:程序博客网 时间:2024/05/20 00:16

Class下有两个方法:1:getResource    它的源码是: public java.net.URL getResource(String name) {        name = resolveName(name);        ClassLoader cl = getClassLoader0();        if (cl==null) {            // A system class.            return ClassLoader.getSystemResource(name);        }        return cl.getResource(name);    } 其中resolveName内容: 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;    }如果传入的路径有 /  那么取 /后面的内容,如果没有 /  找到调用这个方法的class的类限定名(包+类名),取类名前面的包,将 . 转换成 /  ClassLoader cl = getClassLoader0();    cl.getResource(name); 应该是在工程项目下加载资源。 ClassLoader.getSystemResource(name) 当class。为系统类库时,就会根据这个方法在系统类库下找。小结:其实不管路径前面有没有/ 他们会做一个相同的事情,就是根据加载器,定位到classpath下,然后如果有斜杠那么去掉斜杠,作为classpath的资源路径。如果没有斜杠,那么根据加载的类,得到它的包,指明是classpath+包  ,在这个路径下找资源2:getResourceAsStream这个方法和上边的方法实现的寻找资源方式是一样的。就不多讲了。但是这两种有个值得注意的注意的地方。博主eclipse的目录中带有空格。结构,getResource()找不到资源,而且getResourceAsStream()却能找到。非常的郁闷。这其中的原因就是因为getResource()返回的是URL 这个类对空格,中文处理后产生的路径会产生乱码。这导致路径出错了。解决办法很简单。URLDecoder.decode(path,"utf8");   这样就可以通过了,由于对乱码这一块还是非常薄弱,所以就不多加深入了getClassLoader两个方法1:getResource()public ClassLoader getClassLoader() {        ClassLoader cl = getClassLoader0();        if (cl == null)            return null;        SecurityManager sm = System.getSecurityManager();        if (sm != null) {            ClassLoader ccl = ClassLoader.getCallerClassLoader();            if (ccl != null && ccl != cl && !cl.isAncestor(ccl)) {                sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);            }        }        return cl;    }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;    }这里得到加载器,直接去加载classpath下的资源,所以getClassLoader.getResource("xxx")  xxx这里就是classpath下的资源路径。这里值得注意的是:xxx开头不能带/.否则资源找不到,这就是什么原因 关键就是 getBootstrapResource(name)这一块了,sun公司没有提供源码。2:  getResourceAsStream();资源路径处理的方式和上边一样,就不多说了。

先看看下面的代码

public static void main(String[] args) throws IOException {System.out.println(System.getProperty("user.dir"));File flie= new File("bin/file.txt");FileInputStream fis = new FileInputStream(flie);byte[] cache = new byte[1024];if(fis.read(cache)!=-1){System.out.println(new String(cache));}}

该类是在package1包下 file.txt是在src目录下。

在J2EE的一些资源的定位中我们将没有加 / 的路径 作为当前目录下的资源。那么这里 new File("bin/file.txt“)  照理说是在package1下 bin文件夹下的file.txt

而实际在I这里指的就是bin文件夹下的file.txt。 IDE环境中相对路径是工程的根目录。但是如果实在控制台执行那么上边的程序会报FileNotFoundException 所以需要用到绝对路径了.class.getResource()/getResourceAsStream()等读取


接下来探索的话题是jar资源的加载。先看看下面的代码public static void main(String[] args) throws IOException {System.out.println(System.getProperty("user.dir"));File flie= new File("bin/file.txt");FileInputStream fis = new FileInputStream(flie);byte[] cache = new byte[1024];if(fis.read(cache)!=-1){System.out.println(new String(cache));}}该类是在package1包下 file.txt是在src目录下。在J2EE的一些资源的定位中我们将没有加 / 的路径 作为当前目录下的资源。那么这里 new File("bin/file.txt“)  照理说是在package1下 bin文件夹下的file.txt而实际在I这里指的就是bin文件夹下的file.txt。 IDE环境中相对路径是工程的根目录。但是如果实在控制台执行那么上边的程序会报FileNotFoundException 所以需要用到绝对路径了.class.getResource()/getResourceAsStream()等读取jar的资源访问:一个有意思的main我把上面的程序打成了一个jar导入到另外一个工程, 上面的main可以在这个被工程下的类调用,这个还第一次知道 &_^   当然上边的资源会报FileNotFoundException  不是在没打成jar包前测试过了吗,好好的,怎么打成jar后就找不到资源了呢。这就是我当前要探索的东西了。我在功能找了那个导入的jar包发现bin不见了, file.txt直接在jar包的根目录下,那么代码中的bin/file.txt当然是无法定位。 我在新的工程src下加入了一个file.txt文件额,这回找到了。看来jar中的资源路径,会在当前的工程中去找额。发现问题,就要针对这个问题去解决,如何解决,我想到,既然没有bin,那么我用绝对路径写死它。file:/..test.jar/file.txt. 不行吗? 抱歉。还真不行。test.jar这个后缀名都有了,果断是一个文件,难道要访问文件下的资源?好吧。没辙了吧。这里就要用到上边说将的getResource/getResourceAsStream来加载了。当然getClassLoader.getResource和getClassLoader.getResourceAsStream也是一样的效果。在调用jar包的类时,都要用加载器加载这个类,加载器会记录关于这个类的信息,我们就可以通过这点取到资源路径。public void getResource() throws IOException {URL url = ReadResource.class.getResource("/file.txt");String path = url.getPath();path = URLDecoder.decode(path,"utf8");BufferedReader br1 = new BufferedReader(new FileReader(path));System.out.println(br1.readLine());}将这个ReadResource类打成一个jar,导入到Ex项目下。运行,就能准确的读取我在getResource()中加了一行System.out.println(path); 在Ex中运行,得到的路径就是:/F:/Workspaces/Eclipse 3.1/Ex/bin/file.txt这个file.txt就是jar中的资源了。

现在我有个很迷惑的地方,这段代码我从xwork中找出来的。

public static Iterator<URL> getResources(String resourceName, Class callingClass, boolean aggregate) throws IOException {         AggregateIterator<URL> iterator = new AggregateIterator<URL>();         iterator.addEnumeration(Thread.currentThread().getContextClassLoader().getResources(resourceName));         if (!iterator.hasNext() || aggregate) {             iterator.addEnumeration(ClassLoaderUtil.class.getClassLoader().getResources(resourceName));         }         if (!iterator.hasNext() || aggregate) {             ClassLoader cl = callingClass.getClassLoader();             if (cl != null) {                 iterator.addEnumeration(cl.getResources(resourceName));             }         }         if (!iterator.hasNext() && (resourceName != null) && ((resourceName.length() == 0) || (resourceName.charAt(0) != '/'))) {              return getResources('/' + resourceName, callingClass, aggregate);         }         return iterator;     }

如果resourceName没有带斜杠,那么不管通过上边那种方式获得资源他们都是一样的。那么何必多此一举呢?如果带斜杠,那么就像之前说的,资源是找不到的返回一个null。但是这边还是通过这种方式来。这是什么意思了?留着以后补充吧。







原创粉丝点击