BrownieBrown
BrownieBrown

Reputation: 135

Kotlin read/import Map from txt.file

I am working on a learning project, that is supposed to import and export Flashcards to a txt.file which is later supposed to be used in questioning.

Currently, I am stuck on the import part and the research I did is not really working, because I am not really getting it.

I have this overall map where I save the term: definition in a map

private var flashCardMap = mutableMapOf<String, String>()

Then I have this export function

    private fun export() {
        println("File name:")
        scan.nextLine()
        val fileName = scan.nextLine()
        val myFile = File(fileName)
        try {
            myFile.bufferedWriter().use { out->
                flashCardMap.forEach {
                    out.write("${it.key}:${it.value}\n")
                } }
            println("${flashCardMap.size} cards have been saved.")
        } catch (e: FileNotFoundException) {
            println("File not Found.")
        }
    }

which exports all the cards I defined earlier in a txt. file like this with one or more Flashcard (Card = Definition)

key:value

AND here is where I am stuck. I try to import a .txt file and the including map but it does not work. It Is supposed to import the map and tell me how many Cards where imported and the add them to my current flashcardmap with which I am working in this session. Here is what I tried:

    private fun import() {
        println("File name:")
        scan.nextLine()
        val fileName = scan.nextLine()
        val myFile = File("$fileName")
        try {
            val importMap =
            myFile.readLines().chunked(2) {
                it[0] to it[1]
            }.toMap()
            println("${importMap.size} cards have been loaded.")
            flashCardMap.putAll(importMap)
        } catch (e: FileNotFoundException) {
            println("File not Found.")
        }
    }

Upvotes: 4

Views: 1781

Answers (1)

zalpha314
zalpha314

Reputation: 1495

There's actually so many ways to serialize structured data to a file, but since your example uses the key:value format, separated by new-lines, we'll stick with that.

This class should suit your needs. But it's pretty simplistic, and lacks any sort of error handling.

class Serializer(private val filePath: Path, private val delimiter: String = ":") {

    fun export(data: Map<String, String>) {
        filePath.toFile().writer().use { writer ->
            for ((key, value) in data) {
                writer.write("$key$delimiter$value\n")
            }
        }
    }

    fun import(): Map<String, String> {
        val data = mutableMapOf<String, String>()

        filePath.toFile().reader().use { reader ->
            reader.forEachLine { line ->
                val (key, value) = line.split(delimiter)
                data[key] = value
            }
        }

        return data
    }
}

If you want to leverage a mature format, then the built-in java.util.Properties class can make things even easier. The only gotcha is that it uses a = delimiter by default, but it's supposed to be able to read a : delimiter too.

class PropertiesSerializer(private val filePath: Path) {

    fun export(data: Map<String, String>) {
        val props = Properties()

        for ((key, value) in data) {
            props[key] = value
        }

        filePath.toFile().outputStream().use { stream ->
            props.store(stream, null)
        }
    }

    fun import(): Map<String, String> {
        val props = Properties()

        filePath.toFile().inputStream().use { stream ->
            props.load(stream)
        }

        return props
                .map { (key, value) -> key.toString() to value.toString() }
                .toMap()
    }
}

Upvotes: 2

Related Questions