有没有办法获取 Kotlin 中“资源”文件夹中所有文件的列表?
我可以将特定文件读取为
Application::class.java.getResourceAsStream("/folder/filename.ext")
但有时我只想将文件夹“folder”中的所有内容提取到外部目录。
由于我遇到了同样的问题并且找不到具体的答案,所以我不得不自己写一个。
这是我的解决方案:
fun getAllFilesInResources()
{
val projectDirAbsolutePath = Paths.get("").toAbsolutePath().toString()
val resourcesPath = Paths.get(projectDirAbsolutePath, "/src/main/resources")
val paths = Files.walk(resourcesPath)
.filter { item -> Files.isRegularFile(item) }
.filter { item -> item.toString().endsWith(".txt") }
.forEach { item -> println("filename: $item") }
}
这里我解析了 /src/main/resources 文件夹中的所有文件,然后仅过滤常规文件(不包括目录),然后过滤 resources 目录中的文本文件。
输出是资源文件夹中扩展名为 .txt 的所有绝对文件路径的列表。现在您可以使用这些路径将文件复制到外部文件夹。
该任务有两个不同的部分:
对于1,您可以使用Java的
getResource
:
val dir = File( object {}.javaClass.getResource(directoryPath).file )
对于 2,您可以使用 Kotlin 的 File.walk 扩展函数,该函数返回您可以处理的文件的 序列,例如:
dir.walk().forEach { f ->
if(f.isFile) {
println("file ${f.name}")
} else {
println("dir ${f.name}")
}
}
放在一起你可能会得到以下代码:
fun onEachResource(path: String, action: (File) -> Unit) {
fun resource2file(path: String): File {
val resourceURL = object {}.javaClass.getResource(path)
return File(checkNotNull(resourceURL, { "Path not found: '$path'" }).file)
}
with(resource2file(path)) {
this.walk().forEach { f -> action(f) }
}
}
这样,如果您有
resources/nested
direcory,您可以:
fun main() {
val print = { f: File ->
when (f.isFile) {
true -> println("[F] ${f.absolutePath}")
false -> println("[D] ${f.absolutePath}")
}
}
onEachResource("/nested", print)
}
没有任何方法(即
Application::class.java.listFilesInDirectory("/folder/")
),但您可以创建自己的系统来列出目录中的文件:
@Throws(IOException::class)
fun getResourceFiles(path: String): List<String> = getResourceAsStream(path).use{
return if(it == null) emptyList()
else BufferedReader(InputStreamReader(it)).readLines()
}
private fun getResourceAsStream(resource: String): InputStream? =
Thread.currentThread().contextClassLoader.getResourceAsStream(resource)
?: resource::class.java.getResourceAsStream(resource)
然后只需调用
getResourceFiles("/folder/")
,您将获得文件夹中的文件列表,假设它位于类路径中。
这是可行的,因为 Kotlin 有一个扩展函数,可以将行读入字符串列表。声明是:
/**
* Reads this reader content as a list of lines.
*
* Do not use this function for huge files.
*/
public fun Reader.readLines(): List<String> {
val result = arrayListOf<String>()
forEachLine { result.add(it) }
return result
}
这是在 JVM 上迭代JAR 打包资源的解决方案:
fun iterateResources(resourceDir: String) {
val resource = MethodHandles.lookup().lookupClass().classLoader.getResource(resourceDir)
?: error("Resource $resourceDir was not found")
FileSystems.newFileSystem(resource.toURI(), emptyMap<String, String>()).use { fs ->
Files.walk(fs.getPath(resourceDir))
.filter { it.extension == "ttf" }
.forEach { file -> println(file.toUri().toString()) }
}
}