将Source [ByteString,Any]转换为Source [ByteString,IOResult]

时间:2018-08-30 11:36:37

标签: scala akka-stream akka-http

我有一个:

val fileStream: Source[ByteString, Any] = Source.single(ByteString.fromString("Hello"))

Source[ByteString, Any]类型来自akka fileUpload指令:

https://doc.akka.io/docs/akka-http/current/routing-dsl/directives/file-upload-directives/fileUpload.html

我可以将其转换为Source[ByteString, IOResult],还是执行类似于Source.single(ByteString.fromString("Hello"))的其他操作,以使我从字符串中返回Source[ByteString, IOResult]

我可以使用以下方法创建IO结果:

val ioResult: IOResult = IOResult.createSuccessful(1L)

和带有以下内容的ByteString

val byteString: ByteString = ByteString.fromString("Hello")

所以现在我只需要将它们作为Source[ByteString, IOResult]

注意,这仅用于单元测试,我正在测试一个返回Source[ByteString, IOResult]的函数,因此我想创建一个实例(无需创建文件)来声明该函数返回正确的ByteString,我真的不在乎IOResult的{​​{1}}部分。

1 个答案:

答案 0 :(得分:2)

特定于文件上传指令

我怀疑fileUpload的编写者将实现类型保留为Any,以便将来对API进行更改。通过将其保留为Any,他们以后可以将其更改为他们真正想依靠的类型。

因此,即使您能够转换为IOResult,如果升级akka版本并且类型已更改,您也可能会遇到麻烦...

一般的标准化

Source类型参数中的第二种类型指示流将“具体化”为什么。使用您的示例代码,并将Any修改为the actual type NotUsed,我们可以显示流的整个生命周期:

val notUsed : NotUsed = Source.single(ByteString.fromString("Hello"))
                              .toMat(Sink.ignore)(Keep.left)
                              .run()

如您所见,流运行时将其转换为实际值(即已实现)。在上述情况下,值的类型为NotUsed。这是因为您对源单个值的流无能为力。

a stream that operates on a file对比该流:

val file = Paths.get("example.csv")

val fileIOResult: Future[IOResult] = FileIO.fromPath(file)
                                           .to(Sink.ignore)
                                           .run()

在这种情况下,流正在读取文件的内容并将其流式传输到Sink。在这里,了解文件读取是否有任何错误将很有用。为了能够找出文件读取流的执行情况,将其具体化为Future[IOResult],您可以使用它来获取有关文件读取的信息:

fileIOResult foreach { ioResult =>
  println(s"read ${ioResult.count} bytes from file")
}

因此,将Any“转换”为IOResult并没有任何意义。