Saturday, August 4, 2018

Playing with IO in Kotlin

Welcome to this post.

Today I going to cover a very unusual topic. If this problem is matched with you then it will help you to save a lot of time.

So let's start-

Imagine you have a text file of some data and you want to format it and save the data into the JSON file.

Example text file line:
abbey - n. a monastery ruled by an abbot
....
And you have so many lines in the text file.

and your goal is separate, the word and type(part of speech) and description of the word.
so the file output is like
word - abbey
type - n
des - a monastery ruled by an abbot

and save this on  a JSON file
{
    "word": "Abbey",
    "type": "n",
    "des": "a monastery ruled by an abbot"
}

This is our today goal. (If you don't clear the take a look again)

Let's jump in the code-
Create the main method and add try catch block

fun main(args: Array<String>) {
    try {

    } catch (e: Exception) {
        e.printStackTrace()
    }
}

you have to write all the code in the try-catch block.
Create an input and output file name and path variable
val inputName = "definitions.txt"
val outputName = "Output2.json"
val path = "D:/Android/test/"
make sure you select right path. Now make input and output file.
val inputFile = File("$path$inputName")
val outputFile = File("$path$outputName")

you can check is your input file exists or not
println(inputFile.exists())
Output:
true
Note: If your output is false then your path is wrong, select the right path. until you get this output.

Create an instance of Gson
val gson = Gson()
Note: If you don't know how to add the external library, see this tutorial

Now create a Model class-
class Model(
    val word:String,
    val type:String
    val des:String
)
Create an array list of this model
val list = ArrayList<Model>()

Take a look at our data source. This decorated in lines. So we can go through emery lines.
So we run a for loop for every line. Take the buffer reader from the input file and read lines.

for (string in inputFile.bufferedReader(bufferSize = 4096).readLines()) {
}
I use the buffer size 4096 you can use 1024, or any as you want. If you don't have clear knowledge about buffer size then this answer on StackOverflow

create an instance of StringBuilder.
var stringBuilder = StringBuilder()

Step 1: separate the word.
so we read character wise and if we find this sign '-' then stop reading.
for (char in string) {
     if (char == '-') {
          break
     }
     stringBuilder.append(char)
}
so we find our word and that in the StringBuilder
var word = stringBuilder.toString().trim()
Note: use trim() to remove the space.

Step2: separate the type
first remove the word from the string and do the same code as the word. But this time sign is changed. Now sign is '.'
val typesData = string.removePrefix("$word -").trim()
stringBuilder = StringBuilder()
for (char in typesData){
     if (char == '.') {
         break
     }
     stringBuilder.append(char)
}
so we find the type
val type = stringBuilder.toString().trim()

Step 3: separate the description
first, remove the types
val des = typesData.removePrefix("$type.").trim()
so we find the description.

Extra:
we want to capitalize the first char of the word
val cap = word[0].toUpperCase()
word = word.replaceFirst(word[0],cap)

Now create the model and add to the list.
val model = Model(word,type,des)
list.add(model)

So our all word and tyes and des added in the array.

Now our final task is to convert this list to JSON. For this task we use Gson.
//convert list to JSON string
val string = gson.toJson(list)

Create a new output file on the disk.
//crate new file
outputFile.createNewFile()

Now create the instance of file writer and write this json code in the file.
//now write
val writer = FileWriter(outputFile)
writer.write(string)
Don't forget to close the writer.
//close writer
writer.close()

and finally, print a done message.
println("Done")

So everything is done. Now run the program

Output:
Done

So our JSON file:

[{"word":"Abbey","type":"n","des":"a monastery ruled by an abbot"},{"word":"Abide","type":"v","des":"dwell; inhabit or live in"},{"word":"Abound","type":"v","des":"be abundant or plentiful; exist in large quantities"},{"word":"Absence","type":"n","des":"the state of being absent"},{"word":"Absorb","type":"v","des":"assimilate or take in"},{"word":"Abstinence","type":"n","des":"practice of refraining from indulging an appetite especially alcohol"},{"word":"Absurd","type":"j","des":"inconsistent with reason or logic or common sense"},{"word":"Abundant","type":"j","des":"present in great quantity"},{"word":"Abusive","type":"j","des":"characterized by physical or psychological maltreatment"}, ... 

Check the full code on GitHub.

Some other problem:

Problem 1:
This time our output design will same but our input design will be different.
The input pattern is
word    (type) description

See the solution on Github 

Problem 2:
Input pattern:
word = (type) description

Check the solution on Github

That's it today. Today I cover some unusual topics, but this will help you to save time if you have the same problem.

Thank you very much for reading.

Happy coding.

About Author:

I am Shudipto Trafder,
Since 2015, I write android code. I love to implement new ideas. I use java and also kotlin. Now I am learning Flutter. I love to learn new things and also love to share. And that is the main reason to run this blog.


Let's Get Connected: Facebook Twitter Linkedin Github

No comments :