如何在流结束后关闭文件?

时间:2016-01-20 19:14:56

标签: scala akka-stream

我有一个java.io.File序列流。我使用flatMapConcat创建新的Source文件,类似于:

def func(files: List[File]) =
  Source(files)
    .map(f => openFile(f))
    .flatMapConcat(f => Source.fromPublisher(SomePublisher(f)))
    .grouped(10)
    .via(SomeFlow)
    .runWith(Sink.ignore)

有一种简单的方法可以在流结束后关闭每个文件吗? SomePublisher()无法关闭它。

2 个答案:

答案 0 :(得分:1)

因此,如果我理解正确,您可以执行以下操作:对于每个文件,您可以创建数据库对象以打开文件。因此,由于您在代码中打开数据库连接,因此您有责任关闭它。由于您正在使用有限的文件列表,因此您可以按序列存储所有数据库连接,运行流并在流式传输结束后关闭所有连接。

替代方法是让自己的发布者获得文件名,打开数据库连接,从中流,关闭数据库连接。第二个选项允许您从无限的文件列表中流式传输。

如果您想要我的代码片段,请告诉我您该函数的完整来源,我会更新它。

答案 1 :(得分:1)

所以我找到了解决问题的很多方法,但如果你有另一种方法,我也希望看到它。

def someSource(file: File) = {
  val f = openFile(file)

  Source
    .fromPublisher(SomePublisher(f))
    .transform(() => new PushStage[?, ?] {
      override def onPush(elem: ?, ctx: Context[?]): SyncDirective = ctx.push(elem)

      override def postStop(): Unit = {
        f.close()
        super.postStop()
      }
    }
}

def func(files: List[File]) =
  Source(files)
    .flatMapConcat(someSource)
    .grouped(10)
    .via(SomeFlow)
    .runWith(Sink.ignore)