IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> java获取jar包中的文件资源 -> 正文阅读

[Java知识库]java获取jar包中的文件资源

问题描述:
??我们常常在代码中读取一些资源文件(比如图片,音乐,文本等等)。在单独运行的时候这些简单的处理不会有问题。但是当我们把代码打成一个jar包以后,即使将资源文件一并打包,这些东西也找不出来了。此时应该怎么办???

??我们在开发时,读取项目内的资源文件时,可以直接获取该资源文件在文件系统中的绝对路径。但是,一旦导出为jar包,就无法获取到资源文件的绝对路径。打完jar包以后资源(例如xml)等将被放在jar包下的第一层,这时使用上述路径就会错误,无法访问到资源。

一、问题示例

1.1 项目开发时

1
TestPath 文件内容:

package pro;
public class TestPath {
	public TestPath() {}
	public static String getFilePath(String fileName){
		return TestPath.class.getResource(fileName).getPath();
	}
}

主访问工程的main函数调用:

public static void main(String[] args) {
		String path = TestPath.getFilePath("data1.txt");
		System.out.println("path:"+path);
		File file = new File(path);
		if(file.exists() && file.isFile()){
			try {
				InputStream inputStream = new FileInputStream(file);
		        System.out.println(inputStream);
			} catch (Exception e) {
				System.err.println("解析文件"+file.getName()+"异常:");
				e.printStackTrace();
			}
		}
    }

输出结果:

path:/D:/eclipse_powflow/workspace/TestPathPro/bin/pro/data1.txt
java.io.FileInputStream@6bc7c054

1.2 打包成jar后

打包成jar包,并在主工程中引用,如下:
2
再执行main函数,输出结果如下:

path:file:/D:/eclipse_powflow/workspace/Test/lib/TestPathPro.jar!/pro/data1.txt

??我们能够看到,此时的路径并不是文件资源定位符的格式 (jar中资源有其专门的URL形式: jar:!/{entry} )。所以,如果jar包中的类源代码用File f=new File(相对路径);的形式,是不可能定位到文件资源的。这也是为什么源代码打包成jar文件后,调用jar包时会报出FileNotFoundException的症结所在了。
??我们不能用常规操作文件的方法来读取ResourceJar.jar中的资源文件res.txt,但可以通过Class类的getResourceAsStream()方法来获取 ,这种方法是如何读取jar中的资源文件的,这一点对于我们来说是透明的。如下节所示。

二、解决方案

2.1 解决方法

??把资源打入jar包,无论资源文件在系统的什么路径下,jar包中的字节码程序都可以找到该包中的资源。我们可以用类装载器(ClassLoader)来做到这一点:

1、ClassLoader :
??是类加载器的抽象类。它可以在运行时动态的获取加载类的运行信息。 可以这样说,当我们调用.jar中的Resource类时,JVM加载进Resource类,并记录下Resource运行时信息(包括Resource所在jar包的路径信息)。而ClassLoader类中的方法可以帮助我们动态的获取这些信息:
2、public URL getResource(String name):
??查找具有给定名称的资源。资源是可以通过类代码以与代码基无关的方式访问的一些数据(图像、声音、文本等)。并返回资源的URL对象。
3、public InputStream getResourceAsStream(String name):
??返回读取指定资源的输入流。这个方法很重要,可以直接获得jar包中文件的内容。

2.2 实现

1、在TestPath工具类中使用getClassLoader().getResourceAsStream获取资源流数据:

/**增加函数,替换getFilePath()函数,直接获取资源流数据*/
public static InputStream getFileInputStream(String fileName){
		return TestPath.class.getClassLoader().getResourceAsStream(fileName);
	}

注意:fileName如果是xml文件等,直接写文件名即可,例如原来是src/main/xxx.xml,现在直接写main/xxx.xml(src的下级目录)

2、测试打印内容:
主访问工程的main函数调用:

public static void main(String[] args) {
		try {
			InputStream fileIn = TestPath.getFileInputStream("pro/data1.txt");
			BufferedReader reader = new BufferedReader(
					new InputStreamReader(fileIn, 
							StandardCharsets.UTF_8));
			String s = "";
			while ((s=reader.readLine())!=null) {
			    System.out.println(s);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
    }

输出结果:
2

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-05-13 11:38:35  更:2022-05-13 11:39:06 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 22:31:42-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码