You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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目录,代码读取清单后逐个加载文件:

  1. 在resources目录创建xml-files-list.txt,每行写一个文件名:
demo1.xml
demo2.xml
  1. 读取并处理文件:
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 21:22:45