【问题标题】:Exceptions thrown while generating a sequence生成序列时抛出的异常
【发布时间】:2021-05-07 22:41:42
【问题描述】:

我想将一个可能很大的文件从一个地方复制到另一个地方(例如但不限于本地文件系统)。为了将阅读与写作分离,我的复制流程有步骤来执行每个任务:

  • 读取步骤返回一系列行(文件内容)。此步骤会生成文件的每一行,以避免将所有文件内容都放在内存中。
  • 写入步骤写入从上一步接收到的行序列。

嗯,有时读取文件时可能会发生异常,在这种情况下,我希望捕获该异常并返回空的行序列。我一直在阅读如何进行,但我只找到与协程相关的参考资料。并且sequence 生成器不是协程。

编辑:正如 cmets 中所建议的,我避免使用 Either。尽管如此,在文件读取期间可能会引发 IOException。

最后,我以这样的方式结束:

import arrow.syntax.function.compose
import arrow.syntax.function.pipe

import java.io.IOException
import java.io.InputStream

fun asSequenceOfLines(stream: InputStream): Sequence<String> =
  sequence {
      stream.bufferedReader().use {
        // readLine() can throw a IOException during file reading
        var line = it.readLine()
        while (line != null) {
          yield(line)
          line = it.readLine()
        }
      }
  }

// A step for reading a file given its path
fun readFile(): FlowStep = { data ->
  val path = data["input"] as String
  val inputStream = File(path).inputStream()
  try {
    val lines = asSequenceOfLines(inputStream)
    data + mapOf("lines" to lines)
  } catch (e: Exception) {
    // [!] NOT catched exception
    println("[WARN] Error when reading file content $path")
    data + mapOf("lines" to emptySequence<String>())
  }
}

当调用此函数并抛出异常时,我无法捕获它,因为它是在消耗序列时抛出的(通常在编写步骤中)。如何在asSequenceOfLines()调用函数(读取步骤)中捕获异常?

这里有完整的代码:https://pastebin.com/PCarVGP8。我正在使用 Kotlin 1.3.50 和 arrow-kt 0.10.0。

感谢阅读:)

【问题讨论】:

  • 最好不要将异常与 Either 混用。重写您的 if 语句以不使用控制流异常。
  • 我同意@ElPaco 的观点,使用 Either 会使该功能有点混乱。我改变了那个。无论如何,我仍然无法捕获调用者函数中抛出的异常......

标签: kotlin arrow-kt


【解决方案1】:

而且序列生成器不是协程

其实是……不过在这种情况下没关系。

好吧,有时读取文件时可能会发生异常,在这种情况下,我希望捕获该异常并返回一个空的行序列

你知道 Kotlin 和 what they are 中的序列是如何工作的吗? Sequence 是一种使收集处理变得惰性的抽象。 asSequenceOfLines 不是阅读步骤。它只是创建了这个抽象。调用asSequenceOfLines 函数时读取零行。所以,IOException 不能在那个调用中被抛出。

实际读取发生在序列被消耗时。但是 Kotlin 序列无法预测未来,并在一开始就说在第 100500 行会有一个IOException。所以,当IOException 发生时,一些行已经被消耗掉了,并且序列已经不为空了!

如果您无法提前读取所有文件并将其保存在内存中,则需要在写入步骤中处理此异常并恢复所有部分完成的写入作业。

此外,还有一个stdlib method 用于逐行读取(和处理)文本文件。

【讨论】:

  • 感谢您的友好回答@Михаил Нафталь。我知道序列的惰性,这就是我的问题背后的原因:由于实际读取发生在序列被消耗时,我无法找到如何捕获 IOException(并避免在写入步骤中捕获它)
猜你喜欢
  • 1970-01-01
  • 2013-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-07
  • 2015-11-25
  • 1970-01-01
相关资源
最近更新 更多