how to convert scala fs2 stream to string?
Asked Answered
P

2

9

I'm want to know how to convert Scala fs2 Stream to string, from fs2 github readme example:

def converter[F[_]](implicit F: Sync[F]): F[Unit] = {
  val path = "/Users/lorancechen/version_control_project/_unlimited-works/git-server/src/test/resources"

  io.file.readAll[F](Paths.get(s"$path/fs.txt"), 4096)
    .through(text.utf8Decode)
    .through(text.lines)
    .filter(s => !s.trim.isEmpty && !s.startsWith("//"))
    .map(line => fahrenheitToCelsius(line.toDouble).toString)
    .intersperse("\n")
    .through(text.utf8Encode)
    .through(io.file.writeAll(Paths.get(s"$path/fs-output.txt")))
    .compile.drain

}

// at the end of the universe...
val u: Unit = converter[IO].unsafeRunSync()

How to get result to String rather then to another file?

Photoluminescence answered 25/1, 2018 at 10:19 Comment(1)
You have a stream of String elements, do you want to get back a collection of such?Grigg
G
4

If you want get all String elements running in your stream, you can use runFold to materialize it. A simplistic example:

def converter[F[_]](implicit F: Sync[F]): F[List[String]] = {
  val path = "/Users/lorancechen/version_control_project/_unlimited-works/git-server/src/test/resources"

  io.file.readAll[F](Paths.get(s"$path/fs.txt"), 4096)
    .through(text.utf8Decode)
    .through(text.lines)
    .filter(s => !s.trim.isEmpty && !s.startsWith("//"))
    .runFold(List.empty[String]) { case (acc, str) => str :: acc }
}

And then:

val list: List[String] = converter[IO].unsafeRunSync()
Grigg answered 25/1, 2018 at 11:5 Comment(2)
thanks, it works well. Besides, latest fs2(v0.10.0-M11) recommend use compile.fold instand.Photoluminescence
This is not the appropriate solution on more recent versions. .compile.to(List) to aggregate each element into a list or .compile.string to make directly into a singular string. Like the more recent answer below.Trine
R
7

If you have a Stream[F, String], you can call .compile.string to convert your stream to a F[String].

val s: Stream[IO, String] = ???
val io: IO[String] = s.compile.string
val str: String = io.unsafeRunSync()
Rojo answered 28/11, 2019 at 8:30 Comment(0)
G
4

If you want get all String elements running in your stream, you can use runFold to materialize it. A simplistic example:

def converter[F[_]](implicit F: Sync[F]): F[List[String]] = {
  val path = "/Users/lorancechen/version_control_project/_unlimited-works/git-server/src/test/resources"

  io.file.readAll[F](Paths.get(s"$path/fs.txt"), 4096)
    .through(text.utf8Decode)
    .through(text.lines)
    .filter(s => !s.trim.isEmpty && !s.startsWith("//"))
    .runFold(List.empty[String]) { case (acc, str) => str :: acc }
}

And then:

val list: List[String] = converter[IO].unsafeRunSync()
Grigg answered 25/1, 2018 at 11:5 Comment(2)
thanks, it works well. Besides, latest fs2(v0.10.0-M11) recommend use compile.fold instand.Photoluminescence
This is not the appropriate solution on more recent versions. .compile.to(List) to aggregate each element into a list or .compile.string to make directly into a singular string. Like the more recent answer below.Trine

© 2022 - 2024 — McMap. All rights reserved.