gpt4 book ai didi

haskell - 是什么导致了这个 "delayed read on closed handle"错误?

转载 作者:行者123 更新时间:2023-12-04 10:50:18 25 4
gpt4 key购买 nike

我刚刚从最新来源安装了 GHC,现在我的程序给了我一条关于“关闭句柄延迟读取”的错误消息。这是什么意思?

最佳答案

基本的惰性 I/O 原语 hGetContents , 产生 String懒惰地——它只根据需要从句柄中读取,以生成程序实际需要的字符串部分。但是,一旦关闭句柄,就无法再从句柄中读取,如果您尝试检查尚未读取的字符串部分,您将收到此异常。例如,假设你写

main = do
most <- withFile "myfile" ReadMode
(\h -> do
s <- hGetContents h
let (first12,rest) = splitAt 12 s
print first12
return rest)
putStrLn most
GHC 开通 myfile并将其设置为懒惰地读取我们绑定(bind)到 s 的字符串.它实际上并没有开始从文件中读取。然后它设置了一个惰性计算以在 12 个字符后拆分字符串。然后 print强制计算,GHC 读取 myfile block 至少 12 个字符长,并打印出前十二个字符。然后在 withFile 时关闭文件。完成,并尝试打印出其余部分。如果文件比 GHC 缓冲的 block 长,一旦到达 block 的末尾,您将得到延迟读取异常。
如何避免这个问题
在关闭文件或从 withFile 返回之前,您需要确保您已实际阅读了所需的所有内容。 .如果您传递给 withFile 的函数只需执行一些 IO 并返回一个常量(例如 () ),您无需担心这一点。如果您需要它从惰性读取中产生一个真正的值,您需要确保在返回之前充分强制该值。在上面的示例中,您可以使用 Control.DeepSeq 中的函数或运算符将字符串强制为“正常形式”。模块:
return $!! rest
这确保了字符串的其余部分在 withFile 之前被实际读取。关闭文件。 $!!如果您返回的是从文件内容计算的某个值,则该方法也可以很好地工作,只要它是 NFData 的实例即可。类(class)。在这种情况下,以及许多其他情况下,最好将用于处理文件内容的其余代码简单地移动到传递给 withFile 的函数中。 , 像这样:
main = withFile "myfile" ReadMode
(\h -> do
s <- hGetContents h
let (first12,rest) = splitAt 12 s
print first12
putStrLn rest)
另一个要考虑的函数是 readFile . readFile保持文件打开,直到它完成读取文件。您应该只使用 readFile但是,如果您知道您实际上将需要文件的全部内容,否则您可能会泄漏文件描述符。
历史
根据 Haskell 报告,一旦句柄关闭,字符串的内容就固定了。
过去,GHC 只是在句柄关闭时缓冲的任何内容的末尾结束字符串。例如,如果您在关闭句柄之前检查了字符串的前 10 个字符,并且 GHC 缓冲了额外的 634 个字符,但没有到达文件末尾,那么您将获得一个 644 个字符的普通字符串。这是新用户混淆的常见来源,也是生产代码中偶尔出现的错误来源。
从 GHC 7.10.1 开始,这种行为正在发生变化。当你关闭一个你懒惰读取的句柄时,它现在有效地将异常放在缓冲区的末尾,而不是通常的 :"" .因此,如果您尝试检查超出文件关闭点的字符串,您将收到一条错误消息。

关于haskell - 是什么导致了这个 "delayed read on closed handle"错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26949378/

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