如何将Scala fs2 Stream转换为字符串?基于官方示例改造
如何将fs2 Stream转换为字符串
我来帮你调整代码,把原本写入文件的逻辑改成直接输出字符串!
首先,咱们先理清原来的代码逻辑:你通过一系列through操作处理文件内容,最后用.compile.drain来执行整个流的副作用(也就是写入文件),但这个方法会丢弃所有流中的元素,只关心执行完成的状态。要得到字符串结果,咱们需要把compile.drain换成能收集元素并合并成字符串的操作。
这里有两种简洁的修改方式:
方式一:直接收集字符串流
在intersperse("\n")之后,我们已经得到了一个Stream[F, String],可以直接把这些字符串元素合并成一个完整的字符串:
import cats.effect.Sync import fs2.{Stream, io, text} import java.nio.file.Paths def converterToString[F[_]](implicit F: Sync[F]): F[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("//")) .map(line => fahrenheitToCelsius(line.toDouble).toString) .intersperse("\n") // 利用String的Monoid特性,自动拼接所有字符串元素 .compile.foldMonoid } // 调用示例 val result: String = converterToString[IO].unsafeRunSync()
这里用到的compile.foldMonoid是个很方便的方法——因为String本身符合Monoid规则(空字符串是单位元,+是合并操作),它会自动把流里的所有字符串拼接成一个完整的结果。
方式二:从字节流转换为字符串
如果你想保留utf8Encode的步骤(模拟原来的编码逻辑),可以把字节流收集起来再解码成字符串:
import cats.effect.Sync import fs2.{Stream, io, text} import java.nio.file.Paths def converterToString[F[_]](implicit F: Sync[F]): F[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("//")) .map(line => fahrenheitToCelsius(line.toDouble).toString) .intersperse("\n") .through(text.utf8Encode) // 收集所有字节并解码为UTF-8字符串 .compile.string } // 调用示例 val result: String = converterToString[IO].unsafeRunSync()
compile.string是fs2专门提供的便捷方法,它会把流中的所有字节收集起来,再用UTF-8解码成一个完整的字符串,完美适配这种场景。
两种方式都能达到你的需求,你可以根据自己的偏好选择~
内容的提问来源于stack exchange,提问作者LoranceChen
相关产品推荐
相关产品推荐

