Scala项目打包JAR后无法读取内部目录文件的问题排查
解决JAR包中读取内部目录文件的空指针问题
问题根源
JAR本质是压缩归档文件,内部的目录并非操作系统层面的真实目录。你的代码用File类访问JAR内的xml-files路径时,listFiles()会返回null,后续调用map操作就触发了空指针异常。
解决方案
方法一:解析JAR协议枚举内部资源
通过类加载器获取资源URL,识别JAR协议后直接读取JAR包内的条目,筛选目标目录下的文件:
import java.net.URLDecoder import java.util.jar.JarFile import scala.collection.JavaConverters._ val classLoader = getClass.getClassLoader val resourceUrl = classLoader.getResource("xml-files") if (resourceUrl != null) { val decodedPath = URLDecoder.decode(resourceUrl.getPath, "UTF-8") decodedPath match { // 处理JAR包内的资源路径 case jarPath if jarPath.startsWith("jar:") => val jarFilePath = jarPath.substring(4, jarPath.indexOf("!")).replace("file:", "") val jarFile = new JarFile(jarFilePath) // 筛选xml-files目录下的非目录条目 val xmlFilePaths = jarFile.entries().asScala .filter(entry => entry.getName.startsWith("xml-files/") && !entry.isDirectory) .map(_.getName) // 后续可遍历xmlFilePaths处理文件 xmlFilePaths.foreach(println) jarFile.close() // 非JAR环境(如IDE运行)使用原逻辑 case localPath => val dir = new File(localPath) val xmlFilePaths = dir.listFiles().filter(_.isFile).map(_.getPath) xmlFilePaths.foreach(println) } } else { throw new IllegalArgumentException("未找到xml-files资源目录") }
方法二:预配置文件列表(适合固定目录结构)
如果xml-files下的文件列表固定,打包前生成一个文件清单(如xml-files-list.txt)放在resources目录,代码读取清单后逐个加载文件:
- 在resources目录创建
xml-files-list.txt,每行写一个文件名:
demo1.xml demo2.xml
- 读取并处理文件:
import scala.io.Source val listStream = getClass.getClassLoader.getResourceAsStream("xml-files-list.txt") if (listStream != null) { val fileNames = Source.fromInputStream(listStream).getLines() .map(name => s"xml-files/$name") .toList fileNames.foreach { fileName => val fileStream = getClass.getClassLoader.getResourceAsStream(fileName) if (fileStream != null) { // 读取文件内容,示例为转成字符串 val content = Source.fromInputStream(fileStream).mkString println(content) fileStream.close() } } listStream.close() }
注意事项
- 确保
xml-files目录及内部文件在打包时被正确纳入JAR,比如Maven/Gradle默认会打包src/main/resources下的所有内容。 - 永远不要用
File类访问JAR内部资源,这类操作仅适用于文件系统的真实路径。
内容的提问来源于stack exchange,提问作者forvev
相关产品推荐
相关产品推荐

