作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我希望在 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/
我希望在 Haskell 中快速检索文件的最后一行——从末尾开始,而不是从头开始——并且在正确使用 hSeek 时遇到了一些困难。 似乎 SeekFromEnd N 的行为不同于查找文件长度 sz,并
我是一名优秀的程序员,十分优秀!