Kotlin Path.useLines { } - 如何不获取 IOException( "Stream closed" )?



Kotlin有很好的包装和快捷方式,但有时我会被发现不理解它们。

我有一个简化的代码:

class PipeSeparatedItemsReader (private val filePath: Path) : ItemsReader {
override fun readItems(): Sequence<ItemEntry> {
return filePath.useLines { lines -> 
lines.map { ItemEntry("A","B","C","D",) } 
}
}

然后我有:

val itemsPath = Path(...).resolve()
val itemsReader = PipeSeparatedItemsReader(itemsPath)
for (itemEntry in itemsReader.readItems())
updateItem(itemEntry)
// I have also tried itemsReader.readItems().forEach { ... }

这很简单——我希望这段代码能给我一个序列,打开一个文件,读取行,解析它们,并给出ItemEntrys,用完后关闭文件。

然而,我得到的是IOException("Stream closed")

不知怎的,即使在读取第一个项目(我已经调试过(之前,在Kotlin的包装器中的某个地方,reader.in也变成了null,所以在hasNext()中抛出了这个异常。

我在这里看到了一个类似的问题:Kotlin从不同的InputStream链接多个序列?

其中包括许多Java样板,我希望避免使用这些样板。

我应该如何使用Path.useLines()对此序列进行编码

每个Kotlin助手都有"使用";在name中关闭您传递的lambda末尾的底层资源(至少据我所知,这是stdlib中的约定(。最常见的例子是AutoCloseable.use.

Path.useLines扩展也不例外:

调用块回调,为其提供该文件中所有行的序列,并在处理完成后关闭读取器[强调矿]

这意味着一旦块完成,useLines就会关闭行序列,因此您无法从中返回延迟序列,因为在useLines函数返回后您无法使用它。

因此,如果要返回一个行序列供以后使用,则不能直接返回useLines的转换序列。序列实际上无法检测某人何时使用它们,因此useLines需要lambda来给出"0";"范围";或";寿命;到序列,并知道何时关闭底层读取器。

如果您想包装它,您有两个主要选项:要么拆分序列操作和关闭操作(使PipeSeparatedItemsReader可关闭(,要么使用lambda以与useLines相同的方式处理readItems()中的内容。

最新更新