gpt4 book ai didi

haskell - Haskell 中的 hSeek 和 SeekFromEnd

转载 作者:行者123 更新时间:2023-12-02 01:18:03 25 4
gpt4 key购买 nike

我希望在 Haskell 中快速检索文件的最后一行——从末尾开始,而不是从头开始——并且在正确使用 hSeek 时遇到了一些困难。

似乎 SeekFromEnd N 的行为不同于查找文件长度 sz,并使用 AbsoluteSeek(sz - N) 字节。

outh <- openFile "test.csv" ReadMode

λ> hIsSeekable outh
True

λ> hFileSize outh
81619956
λ> hSeek outh AbsoluteSeek 1000
λ> hTell outh
1000

λ> hSeek outh SeekFromEnd 1000
λ> hTell outh
81620956

λ> hSeek outh AbsoluteSeek 0
λ> hGetLine outh
"here's my data"

λ> hSeek outh SeekFromEnd 10000
-*** Exception: test.csv: hGetLine: end of file

嗯,这很奇怪。

所以,我创建了一个函数,用 absolute 代替:

λ> hSeek outh SeekFromEnd 100000
λ> hTell outh
81719956

fromEnd outh = do
sz <- hFileSize outh
hSeek outh AbsoluteSeek (sz - 100000)

λ> fromEnd outh

λ> hTell outh
81519956

所以在输出方面,他们有不同的答案,这很奇怪。此外,我现在还可以使用 hGetLine,SeekFromEnd 失败了:

λ> hGetLine outh
"partial output"
λ> hGetLine outh
"full output, lots of fields, partial output"

我不清楚这里发生了什么。为什么我的 fromEnd 在允许 hGetLine 方面的行为与 SeekFromEnd 不同?

问题的第二部分:从文件末尾开始并向后寻找第一个换行符(EOF 换行符之后的第一个\n)的正确策略是什么?

在这个问题中,我专门使用 SeekFromEnd 寻找答案。

最佳答案

SeekFromEnd 的偏移量应为负数。

至于获取文件的最后一行,我们遇到了一个烦恼,即我们必须从末尾逐个扫描每个字符,每次都重置位置。也就是说,我们可以做到这一点——我们只是继续向后移动,直到遇到第一个 \n 字符。

import System.IO

-- | Given a file handle, find the last line. There are no guarantees as to the
-- position of the handle after this call, and it is expected that the given
-- handle is seekable.
hGetLastLine :: Handle -> IO String
hGetLastLine hdl = go "" (negate 1)
where
go s i = do
hSeek hdl SeekFromEnd i
c <- hGetChar hdl
if c == '\n'
then pure s
else go (c:s) (i-1)

你可能想在这里加一个 off,因为大多数文件通常以 \n 结尾(而那个空行可能不是你想要的)

关于haskell - Haskell 中的 hSeek 和 SeekFromEnd,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41654849/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com