Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 哈斯凯尔的希克和希克弗洛蒙德_Haskell_Mmap - Fatal编程技术网

Haskell 哈斯凯尔的希克和希克弗洛蒙德

Haskell 哈斯凯尔的希克和希克弗洛蒙德,haskell,mmap,Haskell,Mmap,我希望在Haskell中快速检索文件的最后一行——从末尾开始,而不是从开头开始——并且在正确使用hSeek时遇到一些困难 似乎SeekFromEnd N的行为不同于查找文件的长度sz,并使用AbsoluteSeek转到(sz-N)字节 outh <- openFile "test.csv" ReadMode λ> hIsSeekable outh True λ> hFileSize outh 81619956 λ> hSeek outh AbsoluteSeek 10

我希望在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
我不清楚这里发生了什么。为什么我的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)
import System.IO
--|给定文件句柄,查找最后一行。没有任何关于这一点的保证
--此调用后句柄的位置,并且预期给定的
--把手是可以找到的。
hGetLastLine::句柄->IO字符串
hGetLastLine hdl=go“”(取反1)
哪里
去做
hSeek hdl SeekFromEnd i

c似乎
hSeek out SeekFromEnd 1000
在结束后移动到了1000字节!这不应该发生。现在我也很困惑。无论如何,我认为你应该使用偏移-1000。啊,我应该使用古老的减法科学。谢谢,@chi,甚至没有注意到。我想可能是@Mittenchops Fair point的复制品。再次谢谢,@Alec。我还要学哈斯克尔。。。!这在我的机器上运行得非常快。我必须将hGetLastLine hdl=go”“(否定2)更改为与您所说的完全一致,最后一个字符为\n。我想在windows上它需要是3,因为\r\n。。。
λ> hGetLine outh
"partial output"
λ> hGetLine outh
"full output, lots of fields, partial output"
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)