我希望在Haskell程序中选择一个大文本文件(约10GB)中的第n
个最后一行。
我找到了一种从“内部”字符串获取倒数第n
个元素的方法:
myLen = 7
n = 3 -- one-based from the end
myLines = lines myText
idx = myLen - n
theLine = head (drop idx myLines)
main :: IO ()
main = do
putStrLn theLine
readFile
函数的文档说明称它是“惰性读取内容”,那么一旦readFile
到达倒数第n
行时,它是否会将前面的所有行存储在内存中(然后由于我没有那么多内存而发生错误)?
所以,readFile
在这里是否是正确的方法?另外,如何以“惰性方式”从readFile
中获取IO String
输出,并将其转换为行列表,以便我可以选择倒数第n
行?
hSeek
和Data.ByteString中的句柄I/O函数来实现此操作。即使使用惰性字符串,在10GB文件中从前面读取也会非常低效。 - DogbertreadFile
返回的列表执行“单个遍历”,则应该无需将整个列表存储在内存中即可运行。 (请注意,Haskell本地字符串在某种程度上效率低下,惰性字节字符串可能是更好的选择)。或者更准确地说,行将被存储在内存中,但会进行垃圾回收,因此所有内容应以类似恒定的空间运行。 但是,虽然head(drop 10 xs)
是单次遍历,但head(drop(length xs-4)xs
是双次遍历,这肯定会将整个列表存储在内存中。注意。 - chidrop (length xs - 4) xs
,我已经提前知道了行数,这在我的内部字符串演示中用一个单独的变量表示。我不介意对文件进行 一次 完整的遍历,但不想将所有行存储在内存中。 - halloleoextra
包有一个函数takeEnd,可以帮助你。 - beerboy