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 to chain multiple sequences from different InputStream?
那一個包括很多我想避免的Java樣板。
我應該如何使用這個序列編碼Path.useLines()?
uj5u.com熱心網友回復:
每個名稱中帶有“use”的 Kotlin 助手都會在您傳遞的 lambda 末尾關閉底層資源(據我所知,至少這是 stdlib 中的約定)。最常見的例子是AutoCloseable.use。
Path.useLines擴展也不例外:
呼叫塊回呼,為其提供此檔案中所有行的序列,并在處理完成后關閉閱讀器。[強調我的]
這意味著useLines一旦塊完成就關閉行序列,因此您無法從中回傳惰性序列,因為在useLines函式回傳后您無法使用它。
因此,如果要回傳一系列行以供以后使用,則不能useLines直接從 of 回傳轉換后的序列。序列實際上無法檢測到有人何時完成使用它們,因此為什么useLines需要 lambda 來為序列提供“范圍”或“生命周期”并知道何時關閉底層閱讀器。
如果你想包裝它,你有兩個主要選擇:要么拆分序列操作和關閉操作(使你的可關閉),要么使用 lambda 以相同的方式PipeSeparatedItemsReader就地處理事物。readItems()useLines
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/526775.html
標籤:科特林迭代器线序列
