转自:
http://www.iteye.com/topic/483115
我们常常在代码中读取一些资源文件
(
比如图片,音乐,文本等等
)
。在单独运行的时候这些简单的处理当然不会有问题。但是,如果我们把代码打成一个
jar
包以后,即使将资源文件一并打包,这些东西也找不出来了。看看下面的代码:
//
源代码
1
:
package
edu.hxraid;
import
java.io.*;
public
class Resource {
public void getResource() throws IOException{
File file=new File("bin/resource/res.txt");
BufferedReader br=new BufferedReader(new FileReader(file));
String s="";
while((s=br.readLine())!=null)
System.out.println(s);
}
}
这段代码写在
Eclipse
建立的
Java
Project
中,其目录为:
(
其中将资源文件
res.txt
放在了
bin
目录下,以便打成
jar
包
)
1
、
src/
src/edu/hxraid/Resource.java
2
、
bin/
bin/resource/res.txt
bin/edu/hxraid/Resource.class
很显然运行源代码
1
是能够找到资源文件
res.txt
。但当我们把整个工程打成
jar
包以后
(ResourceJar.jar)
,这个
jar
包内的目录为:
edu/hxraid/Resource.class
resource/res.txt
而这时
jar
包中
Resource.class
字节
码:
ldc <String
"bin/resource/res.txt"> [20]
将无法定位到
jar
包中的
res.txt
位置上。就算把
bin/
目录去掉:
ldc <String
"resource/res.txt"> [20]
仍然无法定位到
jar
包中
res.txt
上。
这主要是因为
jar
包是一个单独的文件而非文件夹,绝对不可能通过
"file:/e:/.../ ResourceJar.jar
/resource /res.txt"
这种形式的文件
URL
来定位
res.txt
。所以即使是相对路径,也无法定位到
jar
文件内的
txt
文件
(
读者也许对这段原因解释有些费解,在下面我们会用一段代码运行的结果来进一步阐述
)
。
那么把资源打入
jar
包,无论
ResourceJar.jar
在系统的什么路径下,
jar
包中的字节码程序都可以找到该包中的资源。这会是幻想吗?
当然不是,我们可以用类装载器
(ClassLoader)
来做到这一点:
(1) ClassLoader
是类加载器的抽象类。它可以在运行时动态的获取加载类的运行信息。
可以这样说,当我们调用
ResourceJar.jar
中的
Resource
类时,
JVM
加载进
Resource
类,并记录下
Resource
运行时信息
(
包括
Resource
所在
jar
包的路径信息
)
。而
ClassLoader
类中的方法可以帮助我们动态的获取这些信息
:
● public URL getResource(String
name)
查找具有给定名称的资源。资源是可以通过类代码以与代码基无关的方式访问的一些数据
(
图像、声音、文本等
)
。并返回资源的
URL
对象。
● public InputStream
getResourceAsStream(String name);
返回读取指定资源的输入流。这个方法很重要,可以直接获得
jar
包中文件的内容。
(2)
ClassLoader
是
abstract
的,不可能实例化对象,更加不可能通过
ClassLoader
调用上面两个方法。所以我们真正写代码的时候,是通过
Class
类中的
getResource()
和
getResourceAsStream()
方法,这两个方法会委托
ClassLoader
中的
getResource()
和
getResourceAsStream()
方法
。好了,现在我们重新写一段
Resource
代码
,
来看看上面那段费解的话是什么意思了:
//
源代码
2
:
package
edu.hxraid;
import
java.io.*;
import
java.net.URL;
public
class Resource {
public void getResource() throws
IOException{
//
查找指定资源的
URL
,其中
res.txt
仍然开始的
bin
目录下
URL fileURL=this.getClass().getResource("/resource/res.txt");
System.out.println(fileURL.getFile());
}
public static void main(String[] args) throws IOException {
Resource res=new Resource();
res.getResource();
}
}
运行这段源代码结果:
/E:/Code_Factory/WANWAN/bin/resource/res.txt (../
Code_Factory/WANWAN/..
是
java project
所在的路径
)
我们将这段代码打包成
ResourceJar.jar ,
并将
ResourceJar.jar
放在其他路径下
(
比如
c:\ResourceJar.jar)
。然后另外创建一个
java project
并导入
ResourceJar.jar
,写一段调用
jar
包中
Resource
类的测试代码:
import
java.io.IOException;
import
edu.hxraid.Resource;
public
class TEST {
public static void main(String[] args) throws IOException {
Resource res=new Resource();
res.getResource();
}
}
这时的运行结果是:
file:/C:/ResourceJar.jar!/resource/res.txt
我们成功的在运行时动态获得了
res.txt
的位置。然而,问题来了,你是否可以通过下面这样的代码来得到
res.txt
文件?
File f=new File("C:/ResourceJar.jar!/resource/res.txt");
当然不可能,因为
".../ResourceJar.jar!/resource/...."
并不是文件资源定位符的格式
(jar
中资源有其专门的
URL
形式:
jar:<url>!/{entry}
)
。所以,如果
jar
包中的类源代码用
File f=new File(
相对路径
);
的形式,是不可能定位到文件资源的。这也是为什么源代码
1
打包成
jar
文件后,调用
jar
包时会报出
FileNotFoundException
的症结所在了。
(3)
我们不能用常规操作文件的方法来读取
ResourceJar.jar
中的资源文件
res.txt
,但可以通过
Class
类的
getResourceAsStream()
方法来获取
,这种方法是如何读取
jar
中的资源文件的,这一点对于我们来说是透明的。我们将
Resource.java
改写成:
//
源代码
3
:
package
edu.hxraid;
import
java.io.*;
public
class Resource {
public void getResource() throws IOException{
//
返回读取指定资源的输入流
InputStream
is=this.getClass().getResourceAsStream("/resource/res.txt");
BufferedReader br=new BufferedReader(new InputStreamReader(is));
String s="";
while((s=br.readLine())!=null)
System.out.println(s);
}
}
我们将
java
工程下
/bin
目录中的
edu/hxraid/Resource.class
和资源文件
resource/res.txt
一并打包进
ResourceJar.jar
中,不管
jar
包在系统的任何目录下,调用
jar
包中的
Resource
类都可以获得
jar
包中的
res.txt
资源,再
也不会找不到
res.txt
文件了。
今天写了个程序突然发现源代码可以读,但打入
jar
包后就不行了。最后花了我
2
个多小时才搞明白为什么:
原来我的资源文件名是
BigramDict.dct
但是我在源代码里面写成了:
/ICTCLAS_DICT/b
igramDict.dct (
首字母小写了
)
本来这是个小问题,但是源代码
InputStream is=this.getClass().getResourceAsStream("/ICTCLAS_DICT/bigramDict.dct");
运行的时候是可以找到
BigramDict.dct
的。一旦把
BigramDict.dct
打入
jar
包,就找不到了。
分享到:
相关推荐
主要介绍了解决SpringBoot jar包中的文件读取问题实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
主要介绍了详解Java读取Jar中资源文件及实现代码的相关资料,在开发java项目的时候,经常会用到jar包,这里就说下如何读取,需要的朋友可以参考下
利用swt中的一个获取图片的类SwingResourceManager 来解决将程序打为使用java打包之后,生成的jar包中图片找不着的。这是因为通过class.getResource()方法在IDEA中运行的路径和生成jar包获取的的路径是不同的。打成...
下面小编就为大家带来一篇浅谈两个jar包中包含完全相同的包名和类名的加载问题。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
本篇文章主要介绍了spring boot加载第三方jar包的配置文件的方法,详细的介绍了spring boot jar包配置文件的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
支持从当前运行的spring boot工程jar包中读取javascript,css文件。支持在请求URL携带字符编码名称获取相应的字符编码格式的js、css文件。支持替换css文件中url引用资源的相对路径为可访问的绝对路径。支持使用yui...
JAR:Java档案文件(一种用于applet和相关文件的压缩文件) JAVA:Java源文件 JFF,JFIF,JIF:JPEG文件 JPE,JPEG,JPG:JPEG图形文件 JS:javascript源文件 JSP:HTML网页,其中包含有对一个Java servlet...
程序可以采用 JAVA 开发,但是因为它的虚拟机 (Virtual Machine) Dalvik ,是将 JAVA 的 bytecode 转成 自 己的格式,回避掉需要付给 SUN 有关 JAVA 的授权费用。 对手机制造者的影响 � Android 是款开源的移动计算...
java.util.jar 提供读写 JAR (Java ARchive) 文件格式的类,该格式基于具有可选清单文件的标准 ZIP 文件格式。 java.util.logging 提供 JavaTM 2 平台核心日志工具的类和接口。 java.util.prefs 此包允许应用程序...
实例144 读取jar包文件 215 实例145 文件的加密/解密操作 217 实例146 复制图片 219 实例147 随机读写Java类文件 221 第3篇 Java面向对象编程 第8章 面向对象(教学视频:72分钟) 226 8.1 类 ...
实例144 读取jar包文件 215 实例145 文件的加密/解密操作 217 实例146 复制图片 219 实例147 随机读写Java类文件 221 第3篇 Java面向对象编程 第8章 面向对象(教学视频:72分钟) 226 8.1 类 226 实例148 简单的...
实例144 读取jar包文件 215 实例145 文件的加密/解密操作 217 实例146 复制图片 219 实例147 随机读写Java类文件 221 第3篇 Java面向对象编程 第8章 面向对象(教学视频:72分钟) 226 ...
实例144 读取jar包文件 215 实例145 文件的加密/解密操作 217 实例146 复制图片 219 实例147 随机读写Java类文件 221 第3篇 Java面向对象编程 第8章 面向对象(教学视频:72分钟) 226 8.1 类 226 实例148 简单的...
实例144 读取jar包文件 215 实例145 文件的加密/解密操作 217 实例146 复制图片 219 实例147 随机读写Java类文件 221 第3篇 Java面向对象编程 第8章 面向对象(教学视频:72分钟) 226 8.1 类 226 实例148 ...
java.util.jar 提供读写 JAR (Java ARchive) 文件格式的类,该格式基于具有可选清单文件的标准 ZIP 文件格式。 java.util.logging 提供 JavaTM 2 平台核心日志工具的类和接口。 java.util.prefs 此包允许应用程序...
java.util.jar 提供读写 JAR (Java ARchive) 文件格式的类,该格式基于具有可选清单文件的标准 ZIP 文件格式。 java.util.logging 提供 JavaTM 2 平台核心日志工具的类和接口。 java.util.prefs 此包允许应用程序...
java.util.jar 提供读写 JAR (Java ARchive) 文件格式的类,该格式基于具有可选清单文件的标准 ZIP 文件格式。 java.util.logging 提供 JavaTM 2 平台核心日志工具的类和接口。 java.util.prefs 此包允许应用程序...
java.util.jar 提供读写 JAR (Java ARchive) 文件格式的类,该格式基于具有可选清单文件的标准 ZIP 文件格式。 java.util.logging 提供 JavaTM 2 平台核心日志工具的类和接口。 java.util.prefs 此包允许应用程序...
java.util.jar 提供读写 JAR (Java ARchive) 文件格式的类,该格式基于具有可选清单文件的标准 ZIP 文件格式。 java.util.logging 提供 JavaTM 2 平台核心日志工具的类和接口。 java.util.prefs 此包允许应用程序...