Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin: get list of all files in resource folder

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.

like image 222
Michael Avatar asked Mar 22 '18 03:03

Michael


3 Answers

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.

like image 175
vivek86 Avatar answered Oct 23 '22 20:10

vivek86


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
}
like image 5
Zoe stands with Ukraine Avatar answered Oct 23 '22 18:10

Zoe stands with Ukraine


Two distinct parts:

  1. Obtain a file that represents the resource directory
  2. Traverse the directory

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)
}
like image 4
David Soroko Avatar answered Oct 23 '22 20:10

David Soroko