FS2 is a library for purely functional, effectful, and polymorphic stream processing library in the Scala programming language.
Its design goals are compositionality, expressiveness, resource safety, and speed.
The name is a modified acronym for Functional Streams for Scala (FSS, or FS2).
FS2 is available for Scala 2.12, Scala 2.13, and Scala.js.
FS2 is built upon two major functional libraries for Scala, Cats, and Cats-Effect.
Regardless of those dependencies, FS2 core types (streams and pulls) are polymorphic in the effect type (as long as it is compatible with cats-effect typeclasses),
and thus FS2 can be used with other effect libraries, such as Monix.
Prior to the 0.9 release in 2016, FS2 was known as scalaz-stream, which was based on the scalaz library.
Quick links:
The latest version is 2.2.x. See the badge at the top of the README for the exact version number.
If upgrading from the 1.0 series, see the release notes for 2.0.0 for help with upgrading.
// available for 2.12, 2.13
libraryDependencies += "co.fs2" %% "fs2-core" % "2.2.1" // For cats 2 and cats-effect 2
// optional I/O library
libraryDependencies += "co.fs2" %% "fs2-io" % "2.2.1"
// optional reactive streams interop
libraryDependencies += "co.fs2" %% "fs2-reactive-streams" % "2.2.1"
// optional experimental library
libraryDependencies += "co.fs2" %% "fs2-experimental" % "2.2.1"
The fs2-core library is also supported on Scala.js:
libraryDependencies += "co.fs2" %%% "fs2-core" % "2.2.1"
There are detailed migration guides for migrating from older versions.
FS2 is a streaming I/O library. The design goals are compositionality, expressiveness, resource safety, and speed. Here's a simple example of its use:
import cats.effect.{Blocker, ExitCode, IO, IOApp, Resource}
import cats.implicits._
import fs2.{io, text, Stream}
import java.nio.file.Paths
object Converter extends IOApp {
val converter: Stream[IO, Unit] = Stream.resource(Blocker[IO]).flatMap { blocker =>
def fahrenheitToCelsius(f: Double): Double =
(f - 32.0) * (5.0/9.0)
io.file.readAll[IO](Paths.get("testdata/fahrenheit.txt"), blocker, 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("testdata/celsius.txt"), blocker))
}
def run(args: List[String]): IO[ExitCode] =
converter.compile.drain.as(ExitCode.Success)
}
This will construct a program that reads lines incrementally from testdata/fahrenheit.txt, skipping blank lines and commented lines. It then parses temperatures in degrees Fahrenheit, converts these to Celsius, UTF-8 encodes the output, and writes incrementally to testdata/celsius.txt, using constant memory. The input and output files will be closed upon normal termination or if exceptions occur.
Note that this example is specialised to IO for simplicity, but Stream is fully polymorphic in the effect type (the F[_] in Stream[F, A]), as long as F[_] is compatible with the cats-effect typeclasses.
The library supports a number of other interesting use cases:
Stream being a first class entity with a very rich algebra of combinators.These features mean that FS2 goes beyond streaming I/O to offer a very general and declarative model for arbitrary control flow.
io library provides FS2 bindings for NIO-based file I/O and TCP/UDP networking.fs2.If you have a project you'd like to include in this list, either open a PR or let us know in the gitter channel and we'll add a link to it here.
Chunk that uses shapeless to store case class data column-wise.Sources, Flows and Sinks to and from FS2 Streams, Pipes and Sinks, respectively. It also supports the usage of Apache Camel endpoints in FS2 Streams and Akka Stream Sources, Flows and SubFlows.Special thanks to YourKit for supporting this project's ongoing performance tuning efforts with licenses to their excellent product.
See the Code of Conduct.