Encoding one row at a time

A previous post covered how to encode entire collections as CSV. This is not, however, always possible or even desirable: if the data to encode is obtained in a lazy way, it’s usually better to encoded it as it comes.

kantan.csv provides a useful class for this scenario: CsvWriter, which can be thought of as a highly specialised version of Writer.

First, let’s set up a type to encode as CSV (if the reason why the following code works is not clear, you can read up on it).

import kantan.csv._
import kantan.csv.ops._
import kantan.csv.generic._

case class Person(id: Int, name: String, age: Int)

Obtaining an instance of CsvWriter is achieved by calling the asCsvWriter method that enriches any type that has an implicit instance of CsvSink in scope - or, to keep things simple, any type that you expect to be able to write CSV directly to. You can read up more on that mechanism here.

// File in which we'll be writing the CSV data.
val out = java.io.File.createTempFile("kantan.csv", "csv")

val writer = out.asCsvWriter[Person](rfc.withHeader("Id", "Name", "Age"))

Note the type parameter on asCsvWriter, this is the type that our instance will be able to write.

Now that we have a CsvWriter, we can just send instances of Person to its write method, and call close when we’re done:

writer.write(Person(0, "Nicolas", 38)).
       write(Person(1, "Kazuma", 1)).
       write(Person(2, "John", 18)).
       close()

Note that this is still one of kantan.csv’s rough edges. This code throws, and there currently is no alternative. Future versions will fix that, but for the time being, you need to handle errors by yourself.

Let’s make sure that we get the expected output:

scala.io.Source.fromFile(out).mkString
// res1: String = """Id,Name,Age
// 0,Nicolas,38
// 1,Kazuma,1
// 2,John,18
// """

If you want to learn more about:


Other tutorials: