Skip to content

Instantly share code, notes, and snippets.

@bmc
Last active July 28, 2019 11:04
Show Gist options
  • Save bmc/6d7b16a7634a6f93e8619dcb40efe8b2 to your computer and use it in GitHub Desktop.
Save bmc/6d7b16a7634a6f93e8619dcb40efe8b2 to your computer and use it in GitHub Desktop.
Read a CSV-like, pipe-delimited (jar) resource into Person records, via FS2
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import java.util.Date
import java.text.SimpleDateFormat
import fs2._
// id and gender should really be more strongly-typed, but
// this is just a demo...
case class Person(id: Int,
firstName: String,
middleName: String,
lastName: String,
gender: String,
birthDate: Date,
ssn: String,
salary: Int)
object Thingie {
/** Using fs2.io, read a pipe-delimited text file of
* people from a classpath resource.
*
* @param resource the name of the resource
*
* @return a Future of a Map of (id -> Person).
*/
def readPeople(resource: String): Future[Map[Int, Person]] = {
val cl = this.getClass.getClassLoader
val df = new SimpleDateFormat("yyyy-MM-dd")
Option(cl.getResourceAsStream(resource)).map { is =>
io.readInputStream[Task](Task.now(is), 16 * 1024)
.through(text.utf8Decode)
.through(text.lines)
.drop(1) // drop file header
.filter { line => !line.trim().isEmpty }
.zipWithIndex
.map { case (line, i) =>
line.split("""\|""") match {
case Array(fn, mn, ln, gender, birthDate, salary, ssn) =>
val id = i + 1
(id, Person(id = id,
firstName = fn,
middleName = mn,
lastName = ln,
gender = gender,
birthDate = df.parse(birthDate),
salary = salary.toInt,
ssn = ssn))
case _ =>
throw new Exception(s"""Line ${i+1}: CSV parse error: "$line"""")
}
}
.runLog
.unsafeRunAsyncFuture()
.map(_.toMap)
}
.getOrElse(Future.failed(new Exception(s"Unable to load resource $resource")))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment