Search code examples
scalastreamfs2http4s

FS2: How to get a java.io.InputStream from a fs2.Stream?


Say I have val fs2Stream: Stream[IO, Byte] and I need to, for example, call some Java library that requires a java.io.InputStream.

I suppose that I'm way too new to FS2, but I cannot seem to find the answer. I've tried to use fs2.io.toInputStream and fs2.io.readInputStream but I cannot figure out how to provide some of the required parameters. I've scoured the almighty Google for answers, but it seems that the API has changed since most people were last looking for an answer.

How can I go about doing something like the following?

def myFunc(data: fs2.Stream[IO, Byte]): InputStream[Byte] = someMagicalFunction(data)

Solution

  • You probably want something like this:

    import cats.effect.{ContextShift, IO, Resource}
    import java.io.InputStream
    
    def myFunc(data: fs2.Stream[IO, Byte])
              (implicit cs: ContextShift[IO]): Resource[IO, InputStream] =
      data.through(fs2.io.toInputStream).compile.resource.lastOrError
    

    Then you can use it like:

    object JavaApi {
      def foo(is: InputStream): IO[Unit] = ???
    }
    
    object Main extends IOApp {
      def data: fs2.Stream[IO, Byte] = ???
    
      override def run(args: List[String]): IO[ExitCode] =
        myFunc(data).use(JavaApi.foo).as(ExitCode.Success)
    }
    

    Here is an Scastie with the code running.