我有以下代码片段,它会读取一个CSV文件并只是向控制台输出内容:
def readUsingAkkaStreams = {
import java.io.File
import akka.stream.scaladsl._
import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import java.security.MessageDigest
implicit val system = ActorSystem("Sys")
implicit val materializer = ActorMaterializer()
val file = new File("/path/to/csv/file.csv")
val fileSource = FileIO.fromFile(file, 65536)
val flow = fileSource.map(chunk => chunk.utf8String)
flow.to(Sink.foreach(println(_))).run
}
我现在对此有一些疑问:
chunksize是以字节为单位的大小。它是如何在内部处理的?我的意思是,我最终会遇到一个块可能只包含一行中的部分元素的情况吗?
此流如何终止?现在它没有!我希望它知道它已完全读取文件并应触发停止信号!有机制这样做吗?
编辑1:根据以下帖子的建议,我收到错误消息,如屏幕截图所示!
编辑2:
通过设置maximumFrameLength以匹配最大块大小(65536)的大小来管理以消除错误。
val file = new File("/path/to/csf/file.csv")
val chunkSize = 65536
val fileSource = FileIO.fromFile(file, chunkSize).via(Framing.delimiter(
ByteString("\n"),
maximumFrameLength = chunkSize,
allowTruncation = true))
答案 0 :(得分:1)
1.根据docs:
发出的元素是chunkSize大小的ByteString元素,但最终元素除外,它的大小最多为chunkSize。
FileIO
来源将新行视为任何其他字符。所以是的,你可能会在一个块中看到CSV行的第一部分,而在另一个块中看到第二部分。如果这不是您想要的,您可以使用ByteString
重新构建Framing.delimiter
流的分块方式(有关详情,请参阅docs)。
作为旁注,FileIO.fromFile
已被弃用,请更好地使用FileIO.fromPath
。
一个例子是:
val fileSource = FileIO.fromPath(...)
.via(Framing.delimiter(
ByteString("\n"),
maximumFrameLength = 256,
allowTruncation = true))
2.接收器实现为Future
,您可以映射到流终止时执行某些操作:
val result: Future[IOResult] = flow.runWith(Sink.foreach(println(_)))
result.onComplete(...)