Is there a way to get list of all files in "resources" folder in Kotlin?
I can read specific file as
Application::class.java.getResourceAsStream("/folder/filename.ext")
But sometimes I just want to extract everything from folder "folder" to an external directory.
As I struggled with the same issue and couldn't find a concrete answer, so I had to write one myself.
Here is my solution:
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") }
}
Here I have parsed through all the files in the /src/main/resources folder and then filtered only the regular files (no directories included) and then filtered for the text files within the resources directory.
The output is a list of all the absolute file paths with the extension .txt in the resources folder. Now you can use these paths to copy the files to an external folder.
There are no methods for it (i.e. Application::class.java.listFilesInDirectory("/folder/")
), but you can create your own system to list the files in a directory:
@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)
Then just call getResourceFiles("/folder/")
and you'll get a list of files in the folder, assuming it's in the classpath.
This works because Kotlin has an extension function that reads lines into a List of Strings. The declaration is:
/**
* 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
}
Two distinct parts:
For 1 you can use Java's getResource
:
val dir = File( object {}.javaClass.getResource(directoryPath).file )
For 2 you can use Kotlin's File.walk
extension function that returns a sequence of files which you can process, e.g:
dir.walk().forEach { f ->
if(f.isFile) {
println("file ${f.name}")
} else {
println("dir ${f.name}")
}
}
Put together you may end up with the following code:
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) }
}
}
so that if you have resources/nested
direcory, you can:
fun main() {
val print = { f: File ->
when (f.isFile) {
true -> println("[F] ${f.absolutePath}")
false -> println("[D] ${f.absolutePath}")
}
}
onEachResource("/nested", print)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With