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

Scala打包Jar后如何读取resources下xml-files目录的文件列表?

问题描述

我需要读取/xml-files目录中的文件路径,该目录下存储了多个XML文件。我使用了以下Scala代码:

val xml_folder_2 = getClass.getResource("xml-files")
val dir_path = new File(xml_folder_2.getPath)

但这段代码返回null。我用Paths.get()的版本能正常运行,但因为要把程序打包成Jar文件,所以只能用getClass.getResource()相关方法。

补充说明:目前第一行代码返回的是自动生成的target目录路径,而非resources目录下的路径,这可能是无法列出文件的原因?


解决方案

当程序打包成Jar后,资源目录会被嵌入Jar包内,无法再用File类直接访问(因为Jar里的资源不是文件系统中的真实文件)。以下是适配Jar环境的正确处理方式:

1. 修正资源路径的获取逻辑

getClass.getResource("xml-files")是相对当前类包路径的查找,如果你要访问的是src/main/resources根目录下的xml-files,必须用绝对路径(开头加/):

val resourceUrl = getClass.getResource("/xml-files")

如果仍返回null,先确认xml-files目录确实在src/main/resources下,且构建工具(Maven/Gradle)已将其正确打包进Jar(默认会自动包含resources目录内容)。

2. 读取Jar内目录的文件列表

方法一:兼容开发环境与Jar环境的通用写法

import java.io.IOException
import java.net.URI
import java.nio.file.{FileSystem, FileSystems, Files, Paths}

def listXmlFiles(): List[String] = {
  val resourceUrl = getClass.getResource("/xml-files")
  if (resourceUrl == null) return List.empty

  val uri = resourceUrl.toURI
  // 处理Jar内资源的特殊情况
  val fileSystem: Option[FileSystem] = if (uri.getScheme == "jar") {
    val fs = FileSystems.newFileSystem(uri, Map.empty[String, String])
    Some(fs)
  } else None

  val path = Paths.get(uri)
  val xmlFiles = try {
    Files.list(path)
      .filter(Files.isRegularFile(_))
      .filter(_.toString.endsWith(".xml"))
      .map(_.getFileName.toString)
      .toArray(String(_))
      .toList
  } catch {
    case e: IOException =>
      e.printStackTrace()
      List.empty
  } finally {
    fileSystem.foreach(_.close())
  }

  xmlFiles
}

这段代码会自动适配两种场景:

  • 开发时:直接遍历文件系统中的xml-files目录
  • Jar包中:创建临时文件系统访问Jar内的资源目录

方法二:仅针对Jar环境的直接遍历

如果只需要处理Jar打包后的场景,可以直接读取Jar包本身来筛选资源:

import java.io.IOException
import java.net.URLDecoder
import java.util.jar.JarFile

def listXmlFilesInJar(): List[String] = {
  val jarPath = getClass.getProtectionDomain.getCodeSource.getLocation.getPath
  val decodedPath = URLDecoder.decode(jarPath, "UTF-8")
  val jarFile = new JarFile(decodedPath)
  val entries = jarFile.entries()

  val xmlFiles = collection.mutable.ListBuffer[String]()
  while (entries.hasMoreElements) {
    val entry = entries.nextElement()
    val entryName = entry.getName
    // 筛选xml-files目录下的XML文件
    if (!entry.isDirectory && entryName.startsWith("xml-files/") && entryName.endsWith(".xml")) {
      xmlFiles += entryName.substring("xml-files/".length) // 仅保留文件名
    }
  }

  jarFile.close()
  xmlFiles.toList
}

3. 关键注意事项

  • 确保xml-files目录在src/main/resources根目录下,避免路径层级错误
  • 绝对不要用File类处理Jar内的资源,因为Jar内的资源不是文件系统中的真实文件
  • 路径开头的/表示相对于resources根目录,不加/则是相对于当前类的包路径

内容的提问来源于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 19:42:56