-
2022-03-18 16:37:04
- 我们常常在代码中读取一些资源文件(比如图片,音乐,文本等等)。在单独运行的时候这些简单的处理当然不会有问题。但是,如果我们把代码打成一个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包)
|- src/
src/edu/hxraid/Resource.java
|- 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)来做到这一点:
- ClassLoader 是类加载器的抽象类。它可以在运行时动态的获取加载类的运行信息。 可以这样说,当我们调用ResourceJar.jar中的Resource类时,JVM加载进Resource类,并记录下Resource运行时信息(包括Resource所在jar包的路径信息)。而ClassLoader类中的方法可以帮助我们动态的获取这些信息:
- public URL getResource(String name)
查找具有给定名称的资源。资源是可以通过类代码以与代码基无关的方式访问的一些数据(图像、声音、文本等)。并返回资源的URL对象。 - public InputStream getResourceAsStream(String name)
返回读取指定资源的输入流。这个方法很重要,可以直接获得jar包中文件的内容。
- 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:!/{entry} )。所以,如果jar包中的类源代码用File f=new File(相对路径);的形式,是不可能定位到文件资源的。这也是为什么源代码1打包成jar文件后,调用jar包时会报出FileNotFoundException的症结所在了。
- 我们不能用常规操作文件的方法来读取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文件了。
文章原文链接
公众号相关示例
更多相关内容 -
Spring自动扫描无法扫描jar包中bean的解决方法
2020-08-30 06:01:01在日常开发中往往会对公共的模块打包发布,然后调用公共包的内容。...spring却无法扫描到相应的bean,下面这篇文章主要给大家介绍了关于Spring自动扫描时无法扫描jar包中bean的解决方法,需要的朋友可以参考下。 -
从rom包中提取boot.img
2022-03-03 14:52:371. 下载系统ROM包 2. 解压系统包(只需要payload.bin文件) 3. 复制解压出来的【payload.bin】文件到Payload解包工具的payload_input文件夹 4. 打开【payload_dumper.exe】执行解包(解包需要点时间) ... -
解决SpringBoot jar包中的文件读取问题实现
2020-09-07 18:42:40主要介绍了解决SpringBoot jar包中的文件读取问题实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧 -
Java实现从jar包中读取指定文件的方法
2020-08-29 16:45:08主要介绍了Java实现从jar包中读取指定文件的方法,涉及java针对jar文件的读取及查找相关操作技巧,需要的朋友可以参考下 -
Android 如何实现exclude aar包中的某个jar包
2020-08-19 11:27:16主要介绍了Android 如何实现exclude aar包中的某个jar包,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧 -
删除jar包中的指定文件
2019-08-05 01:31:14NULL 博文链接:https://hw1287789687.iteye.com/blog/2063620 -
kettle调用jar包中的方法.txt
2021-08-03 10:20:19kettle中使用功能java和JavaScript调用jar中的方法示例 -
java打包成jar并执行jar包中指定的main方法
2020-08-31 00:46:38主要介绍了如何将java打包成可执行的jar,并执行jar包中指定的main方法的相关资料,文中给出了详细的示例代码,对大家具有一定的参考价值,需要的朋友们下面来一起看看吧。 -
浅谈两个jar包中包含完全相同的包名和类名的加载问题
2020-08-29 12:26:14下面小编就为大家带来一篇浅谈两个jar包中包含完全相同的包名和类名的加载问题。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧 -
读取ros包中rgb和depth图,python代码
2020-11-05 14:28:36可以将ros包中的颜色图和深度图读取出来,并保存到对应文件夹下。 使用时仅需要修改对应话题和路径即可。 -
springboot编译jar包后无法扫描子jar包中的注解解决方法
2018-11-11 16:25:18springboot 项目编译后无法扫描加载到子jar包中的注解解决方法 -
在cn.com.my包中,封装一个接口Sortable,包括一个抽象方法int compare( Sortable s),表示需要进行比较大小
2020-12-22 03:11:48在cn.com.my包中,封装一个接口Sortable,包括一个抽象方法int compare( Sortable s),表示需要进行比较大小,返回正数则表示大于,返回负数则表示小于,返回0则表示等于。封装一个类Student,要求实现此接口,必须... -
jar包中关键字搜索
2017-02-08 11:23:17寻找指定路径下jar包中含特定字符串的文件 -
java io包中简单的常用类使用
2019-04-05 01:36:27NULL 博文链接:https://mrpengpengda.iteye.com/blog/1536292 -
.net c# 读取解析ios.ipa包中被优化后的png图标
2019-03-15 14:54:05当拿到一个app.ipa包时,想用程序读取包中的资源文件,这时是无法直接将app图标在浏览器被正确解析的,原因是苹果在打包app时,对这些图标文件做了优化处理,crush掉了png图标包含的一些信息,这时我们需要decrush... -
同一个package的类型分散在不同JAR包中
2019-05-27 02:40:53NULL 博文链接:https://rednaxelafx.iteye.com/blog/600619 -
如何重写 jar 包中的方法 jar包中的类
2022-07-01 14:33:22如何重写 jar 包中的方法 jar包中的类在工作中有时候一些业务场景,已封装的jar包里面的部分方法无法满足,这时候就需要我们将这部分方法进行重写已来满足业务需要。
两种方法:
第一种
重写步骤:
1.找到你所要重写的方法的所在类,查看其中的路径;2.在我们的src目录下新建一个同包名同类名的类;
3.将jar包中的重写方法所在类的所有代码复制到我们新建的同包名同类名的类中;
4.在我们新建的同包名同类名的类中修改对应的方法中的代码,注意要保持方法中的参数不要发生改变,
也不要删除原类中已有的方法,但是可以新增一些方法。原理:
编译输出的时候会优先使用我们src下面的类,而不是优先使用Jar包里面的类,这样就达到了覆盖jar包方法的目的。
注-如果遇到重写后方法没有生效,原因有以下两点:
1.检查重新的包路劲是否和源码中的路径一致,可以点到源码看是否有对应的重新方法。
2.如果是maven项目直接放到java目录下面即可,如果是WebContent项目可直接放到src下。第二种
在不影响项目目录结构的情况下可以使用这种方式:
1.找到你所要重写的方法的所在类,查看其中的路径;
2.在我们的src目录下新建一个同包名同类名的类;
3.将jar包中的重写方法所在类的所有代码复制到我们新建的同包名同类名的类中;
4.在我们新建的同包名同类名的类中修改对应的方法中的代码,注意要保持方法中的参数不要发生改变,
也不要删除原类中已有的方法,但是可以新增一些方法。5、将同包名同类名的类重写好,将.java文件编译成.class文件。
6、桌面新建一个文件夹,将编译好的.class文件存进去。
7、打开jar包所在的文件目录
6、使用压缩软件预览jar包中的class文件
7、将 jar 包中需要替换的类删除(jar中的原文件),把自己编译好的.class文件复制进去。
8、替换
9、删除在我们的src目录下新建的包、类。 -
llvm-base-types:一些高级 LLVM 相关包中使用的类型定义
2021-07-03 09:17:37这个包定义了 llvm-analysis 和 llvm-data-interop 包中使用的类型。 这是一个单独的包,主要是因为由于 C++ 链接问题需要拆分 llvm-data-interop。 llvm-data-interop 需要这个包中的定义,但不能依赖 llvm-... -
Python 读取位于包中的数据文件
2021-01-19 23:48:50你的包中包含代码需要去读取的数据文件。你需要尽可能地用最便捷的方式来做这件事。 解决方案 假设你的包中的文件组织成如下: mypackage/ __init__.py somedata.dat spam.py 现在假设spam.py文件需要读取... -
fryingpane:从RStudio连接窗格内的包中服务数据集
2021-04-24 19:41:54从RStudio连接窗格内的包中提供数据集。 安装 您可以使用以下方法从安装{fryingpane}的开发版本: # install.packages("remotes") remotes :: install_github( " ColinFay/fryingpane " ) 这是什么意思 在你的包裹... -
Java解压缩ZIP文件同时包含Jar包解决ZIP包中含有中文名称信息的文件
2019-03-05 01:25:57博文链接:https://peng-jian-ming.iteye.com/blog/190572 -
java获取jar包中的文件资源
2022-05-11 17:04:01java获取jar包中的文件资源 一、问题示例 1.1 项目开发时 1.2 打包成jar后 二、解决方案 2.1 解决方法 2.2 实现 问题描述: 我们常常在代码中读取一些资源文件(比如图片,音乐,文本等等)。在单独运行的时候这些...问题描述:
我们常常在代码中读取一些资源文件(比如图片,音乐,文本等等)。在单独运行的时候这些简单的处理不会有问题。但是当我们把代码打成一个jar包以后,即使将资源文件一并打包,这些东西也找不出来了。此时应该怎么办???我们在开发时,读取项目内的资源文件时,可以直接获取该资源文件在文件系统中的绝对路径。但是,一旦导出为jar包,就无法获取到资源文件的绝对路径。打完jar包以后资源(例如xml)等将被放在jar包下的第一层,这时使用上述路径就会错误,无法访问到资源。
一、问题示例
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包,并在主工程中引用,如下:
再执行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(); } }
输出结果:
-
Android将so库封装到jar包中并加载其中的so库
2021-01-20 08:40:16Android将so库封装到jar包中并加载其中的so库 之前写过将jar包和so库封装到jar包中的文章,但是没有考虑别人调用时需要加载so库的问题。因为so库放入jar之后,so就不是一个独立的.so文件了,用System.load()加载就会... -
Python 分发包中添加额外文件的方法
2021-01-20 06:12:25在制作一个 Python 分发包时经常需要把一些文件添加到包中。最常见的例子是你希望通过 pip install 命令安装 Python 包时会在 /etc/ 等目录下自动添加默认配置文件,由此可以让 Python 安装完成就可以工作,同时... -
重写 jar 包中的方法 jar包中的类
2021-05-22 11:50:373.将jar包中的重写方法所在类的所有代码复制到我们新建的同包名同类名的类中; 4.在我们新建的同包名同类名的类中修改对应的方法中的代码,注意要保持方法中的参数不要发生改变, 也不要删除原类中已有的方法,但是...序言
东西不多,简单明了。
重写jar的两种方式
第一种
重写步骤:
1.找到你所要重写的方法的所在类,查看其中的路径;
2.在我们的src目录下新建一个同包名同类名的类;
3.将jar包中的重写方法所在类的所有代码复制到我们新建的同包名同类名的类中;
4.在我们新建的同包名同类名的类中修改对应的方法中的代码,注意要保持方法中的参数不要发生改变,
也不要删除原类中已有的方法,但是可以新增一些方法。原理:
编译输出的时候会优先使用我们src下面的类,而不是优先使用Jar包里面的类,这样就达到了覆盖jar包方法的目的。
第二种
在不影响项目目录结构的情况下可以使用这种方式:
1-4 的步骤与第一种方式的1-4步骤相同。
5、将同包名同类名的类重写好,将.java文件编译成.class文件。
6、桌面新建一个文件夹,将编译好的.class文件存进去。
7、打开jar包所在的文件目录
6、使用压缩软件预览jar包中的class文件
压缩软件我用的Bandzip
7、将 jar 包中需要替换的类删除(jar中的原文件),把自己编译好的.class文件复制进去。
8、替换
9、删除在我们的src目录下新建的包、类。 -
以下哪个符号用于从包中导入模块:
2021-01-14 01:14:56【判断题】设R,S集合X上的等价关系,则R=S 当且仅当 X/R=X/S。【单选题】病理学的主要研究方法中,下列应除外的是( )...= 4: sum += i i = i+1 int(sum) 代码输出的结果是:【单选题】以下哪个符号用于从包中导入模块... -
得到jar包中所有函数和包名
2014-04-02 00:36:27得到jar包中所有函数和包名,函数背景:希望得到jar包中所有函数和包名,便于在客户端以树型结构展示 -
获取jar包中jar包中的class
2020-07-12 18:01:10上篇写了获取jar包中的class文件,在IDEA运行的好好的, 打个包丢服务器上就跑不了了。 原因就是打成jar包之后获取到的class文件路径变成/demo/xxx.jar!/WEB-INF/lib/yyy.jar!/com/demo/zzz.class了,在IDEA中只要...