Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 104 additions & 3 deletions docs/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ object Main extends CommandIOApp("mkString", "Concatenates strings from stdin")

## Parsing and transforming a CSV file

Here, [fs2-data-csv] is used to read and parse a comma separated file.
Here, [fs2-data-csv] is used to read and parse a comma separated file.
Manual encoders and decoders are defined for our `Passenger`s to show you how to do everything from scratch.

Let's start with a CSV file that has records of fictious passengers registered for a flight:
Expand Down Expand Up @@ -233,7 +233,7 @@ val input = Files[IO]

object CSVPrinter extends IOApp.Simple:

/** First we'll do some logging for each row,
/** First we'll do some logging for each row,
* and then calculate and print the mean age */
val run =
input
Expand Down Expand Up @@ -310,7 +310,7 @@ object CSVPrinter extends IOApp.Simple {
.through(decodeUsingHeaders[Passenger]())


/** First we'll do some logging for each row,
/** First we'll do some logging for each row,
* and then calculate and print the mean age */
val run =
input
Expand Down Expand Up @@ -420,6 +420,107 @@ object PerftConverter extends IOApp.Simple {
```
@:@

## Writing data to a CSV file

If you want to save a list of a case class into a CSV file this utility may aid you:

```scala
// Define your case class and derive an encoder for it
case class YourCaseClass(n: String, i: Int)
given CsvRowEncoder[YourCaseClass, String] = deriveCsvRowEncoder

// Writes a case class as a csv given a path.
def writeCaseClassToCsv[A](
path: Path
)(using CsvRowEncoder[A, String]): Pipe[IO, A, Nothing] =
_.through(encodeUsingFirstHeaders(fullRows = true))
.through(fs2.text.utf8.encode)
.through(Files[IO].writeAll(path))
```
Comment on lines +427 to +439
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's scala 3 only, can you add the scala 2 tab too?


As an example, let's imagine we have a `Book` class we would like to write to a `.csv` file.

@:select(scala-version)

@:choice(scala-3)
```scala mdoc:reset:silent
//> using lib "org.typelevel::toolkit::@VERSION@"

import fs2.data.csv.*
import fs2.data.csv.generic.semiauto.*
import fs2.io.file.{Files, Path}
import cats.effect.{IO, IOApp}
import fs2.{Pipe, Stream}

def writeCaseClassToCsv[A](
path: Path
)(using CsvRowEncoder[A, String]): Pipe[IO, A, Nothing] =
_.through(encodeUsingFirstHeaders(fullRows = true))
.through(fs2.text.utf8.encode)
.through(Files[IO].writeAll(path))


object WriteBooksToCsv extends IOApp.Simple:
case class Book(id: Long, name: String, isbn: String)
given CsvRowEncoder[Book, String] = deriveCsvRowEncoder

val input = Seq(
Book(1, "Programming in Scala", "9780997148008"),
Book(2, "Hands-on Scala Programming", "9798387677205"),
Book(3, "Functional Programming in Scala", "9781617299582")
)

def run: IO[Unit] =
Stream
.emits(input)
.through(writeCaseClassToCsv(Path("books.csv")))
.compile
.drain *> IO.println("Finished writing books to books.csv.")
```

@:choice(scala-2)

```scala mdoc:reset:silent
//> using lib "org.typelevel::toolkit::@VERSION@"

import fs2.data.csv._
import fs2.data.csv.generic.semiauto._
import fs2.io.file.{Files, Path}
import cats.effect.{IO, IOApp}
import fs2.{Pipe, Stream}

object Helpers {
def writeCaseClassToCsv[A](
path: Path
)(implicit encoder: CsvRowEncoder[A, String]): Pipe[IO, A, Nothing] =
_.through(encodeUsingFirstHeaders(fullRows = true))
.through(fs2.text.utf8.encode)
.through(Files[IO].writeAll(path))
}

object WriteBooksToCsv extends IOApp.Simple {
case class Book(id: Long, name: String, isbn: String)
implicit val csvRowEncoder: CsvRowEncoder[Book, String] = deriveCsvRowEncoder

val input = Seq(
Book(1, "Programming in Scala", "9780997148008"),
Book(2, "Hands-on Scala Programming", "9798387677205"),
Book(3, "Functional Programming in Scala", "9781617299582")
)

def run: IO[Unit] =
Stream
.emits(input)
.through(Helpers.writeCaseClassToCsv(Path("books.csv")))
.compile
.drain *> IO.println("Finished writing books to books.csv.")
}
```

@:@



[fs2]: https://fs2.io/#/
[fs2-data-csv]: https://fs2-data.gnieh.org/documentation/csv/
[decline]: https://ben.kirw.in/decline/
Expand Down