【发布时间】:2012-12-01 20:30:39
【问题描述】:
我想使用 Haskell 函数
readFile :: FilePath -> IO String
将文件的内容读入字符串。在the documentation 中,我读到“文件被延迟读取,按需读取,就像 getContents 一样。”
我不确定我是否完全理解这一点。例如,假设我写
s <- readFile "t.txt"
当这个动作被执行时:
- 文件已打开。
- s 中的字符实际上是在需要评估某些表达式时(但不会更早)从文件中读取的(例如,如果我评估
length sall 文件的内容将被读取并且文件将被关闭)。 - 读取完最后一个字符后,与对
readFile的调用相关联的文件句柄就会关闭(自动)。
我的第三个陈述正确吗?那么,我可以只调用readFile 而不自己关闭文件句柄吗?只要我没有消耗(访问)整个结果字符串,句柄会保持打开状态吗?
编辑
这里有一些关于我的疑虑的更多信息。假设我有以下内容:
foo :: String -> IO String
foo filename = do
s <- readFile "t.txt"
putStrLn "File has been read."
return s
当putStrLn 被执行时,我会(直觉地)期待
-
s包含文件t.txt的全部内容, - 用于读取文件的句柄已关闭。
如果不是这样:
-
s在执行putStrLn时包含什么? -
putStrLn执行时文件句柄处于什么状态? - 如果
putStrLn执行时s不包含文件的全部内容,什么时候会真正读取到这个内容,什么时候会关闭文件?
【问题讨论】:
-
即使您愿意,您也无法自行关闭手柄。
hGetContents将手柄置于半关闭状态,参见docs。 -
这是否意味着文件大部分时间都是关闭的(从操作系统的角度来看),而 Haskell 只是在需要字符时临时打开并读入内存缓冲区? (从问题中读取文档,看起来像半封闭 = 出于锁定目的而打开。)
-
@Cat Plus Plus 感谢您的链接!如果我理解正确:当我到达文件末尾时,句柄将自动关闭。但是,如果我在评估整个字符串之前关闭句柄,结果将被截断。
-
我也不明白我的sn-p中
s的类型是什么。如果是字符串,怎么能懒惰地读取呢?懒得看,不应该有一个以某种方式包含IO的类型吗? -
@Giorgio:是的,不是吗?由于这个原因,延迟 IO 有点争议。另见What's so bad about Lazy I/O?
标签: haskell io lazy-evaluation