编写Java外部类库时如何正确读取Jar包内的资源文件
问题根因
报java.nio.file.NoSuchFileException的核心原因是:项目A打包为JAR后,内部的txt文件不再是磁盘上独立存在的文件,而是被压缩在JAR归档包内部。你之前大概率用了File、Paths.get()这类面向磁盘文件系统的API读取,这类API无法识别JAR包内部的归档路径,自然找不到文件。
类路径下的资源(包括依赖JAR里的资源),必须用类加载器提供的资源流接口读取,不能用本地文件路径的读取逻辑。
实现步骤
1. 先确保资源被正确打进JAR
如果构建后txt根本没进JAR,什么读取方式都没用:
- 最规范的做法是遵循Maven/Gradle的标准目录约定,把三个txt文件从
src/main/java/packageTwo挪到src/main/resources/packageTwo目录下,构建工具会默认把resources目录下的所有文件按原结构打进JAR,最终JAR内的路径是/packageTwo/ImportantTextOne.txt,和A.class处于同个类路径层级。 - 如果你坚持要把txt和Java源码放在同个
src/main/java目录下,需要修改构建配置:比如Maven要在pom.xml的<build>标签下添加资源规则,指定编译时把src/main/java下的.txt文件一并纳入打包范围,否则构建时只会拷贝编译出来的.class文件,txt会被漏掉。
2. 正确的资源读取代码
在A.java中直接用当前类的getResourceAsStream方法读同包资源即可,这种方式不依赖磁盘路径,不管项目A是本地调试运行,还是作为JAR被其他项目引入,都能正常定位到资源:
package packageTwo; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.stream.Collectors; public class A { private void loadInternalResources() throws IOException { // 读取同包下的ImportantTextOne.txt // 路径不带开头的/时,是相对当前类所在包的相对路径,适配同包资源场景 try (InputStream is = A.class.getResourceAsStream("ImportantTextOne.txt"); BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { String textContent = reader.lines().collect(Collectors.joining(System.lineSeparator())); // 这里写你的文本处理逻辑 } // 另外两个文件用相同方式读取即可 try (InputStream is2 = A.class.getResourceAsStream("ImportantTextTwo.txt")) { // 处理第二个文件内容 } try (InputStream is3 = A.class.getResourceAsStream("ImportantTextThree.txt")) { // 处理第三个文件内容 } } }
路径写法说明
- 用
类名.class.getResourceAsStream()时,路径开头不加/代表相对当前类所在包查找资源,最适合你当前的场景 - 如果路径开头加
/,比如/packageTwo/ImportantTextOne.txt,就是从类路径根目录开始查找的绝对路径,两种写法都可正常运行,按需选择即可 - 绝对不要写
src/main/java/packageTwo/xxx.txt这类开发阶段的本地磁盘路径,打包后这个路径在运行环境中不存在
3. 常见避坑点
- 不要先调用
getResource()拿到URL再转成File或者Path对象读取:JAR内资源的URL是jar:file:/path/to/xxx.jar!/packageTwo/xxx.txt这种特殊的归档协议路径,文件系统API无法识别,还是会抛文件找不到的错误,直接拿流读就对了 - 读取流时显式指定字符集(比如上面代码里的
StandardCharsets.UTF_8),不要依赖系统默认字符集,避免跨环境运行时出现乱码 - 用try-with-resources语法包裹流对象,自动关闭资源,避免内存泄漏
验证方法
重新构建项目A生成JAR后,直接用解压软件打开JAR包,确认三个txt文件和A.class都在packageTwo目录下,之后把这个JAR引入到任意外部项目调用,都不会再出现文件找不到的报错。
内容的提问来源于stack exchange,提问作者Aditya
相关产品推荐
相关产品推荐

