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
相关产品推荐
相关产品推荐

