问题描述
我想将一个潜在的巨大文件从一个地方复制到另一个地方(例如但不限于本地文件系统)。为了将阅读与写作分离,我的复制流程有步骤来执行每个任务:
好吧,有时在读取文件时可能会发生异常,在这种情况下,我想捕获该异常并返回一个空的行序列。我一直在阅读如何继续,但我只找到与协程相关的参考资料。而 sequence
生成器不是协程。
EDIT:正如评论中所建议的,我避免使用任何一种。尽管如此,在文件读取过程中可能会抛出 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。
感谢阅读:)
解决方法
而且序列生成器不是协程
实际上,它是......但在这种情况下无关紧要。
好吧,有时在读取文件时可能会发生异常,在这种情况下,我想捕获该异常并返回空的行序列
您了解 Kotlin 中的序列如何工作和 what they are 吗? Sequence
是一种使集合处理变得惰性的抽象。 asSequenceOfLines
不是阅读步骤。它只是创建了这种抽象。调用 asSequenceOfLines
函数时读取零行。因此,不能在该调用中抛出 IOException
。
实际读取在序列被消耗时发生。但是 Kotlin 序列无法预测未来,并且一开始就说第 100500 行会有一个 IOException
。所以,当 IOException
发生时,一些行已经被消耗掉,序列已经不为空!
如果您无法提前读取所有文件并将其保存在内存中,则需要在写入步骤中处理此异常并恢复所有部分完成的写入作业。
此外,还有一个 stdlib method 用于逐行读取(和处理)文本文件。