有没有办法在 Kotlin 中获取“resources”文件夹中所有文件的列表?
我可以像这样读取特定文件:
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 文件夹中的所有文件,并仅筛选出常规文件(不包括目录),然后过滤出资源目录中的文本文件。
输出是资源文件夹中所有扩展名为.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
目录,你可以:
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
}
private fun getResourceList(path: String): List {
val stream = Application::class.java.getResourceAsStream(path) ?: return emptyList()
return stream.bufferedReader().use { it.readLines() }
}
- Michaelresource::class.java
总是会引用 String::class.java
,这可能不是您想要的。 - Simon ForsbergThread.currentThread().contextClassLoader.getResourceAsStream(resource)
至少优先于我当时想的任何东西。 - Zoe stands with Ukraine这里有一个在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()) }
}
}
这里是我找到的一个相当简单的解决方案。
File("/path/to/file.txt")
// make an iterable file tree
.walk()
// only files no directories
.filter { it.isFile }
// last modified from top to bottom (most recent on top)
.sortedByDescending { it.lastModified() }
// do things on the files
.forEachIndexed {
i, it ->
// use the most recent file and delete the other ones
if (i == 0) {
useMe(it)
} else {
it.delete()
}
}
.sortedByDescending { it.lastModified() }
?这从未是问题的一部分。 - Simon Forsberg
"/src/main/resources"
将无法工作。 - Simon Forsberg