gpt4 book ai didi

haskell - 读取文件后 Haskell 文件会自动关闭吗?

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

我想使用 Haskell 函数

readFile :: FilePath -> IO String

将文件的内容读入字符串。在 the documentation我已经读过“文件被延迟读取,按需读取,就像 getContents 一样。”

我不确定我是否完全理解这一点。例如,假设我写
s <- readFile "t.txt"

执行此操作时:
  • 文件被打开。
  • s 中的字符实际上是在需要评估某些表达式时立即(但不是更早)从文件中读取的(例如,如果我评估 length s all ,则将读取文件的内容并且文件将被关闭)。
  • 一旦读取了最后一个字符,与此调用相关的文件句柄就到 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不包含文件的全部内容,什么时候会真正读取这个内容,什么时候会关闭文件?
  • 最佳答案

    Is my third statement correct?


    不完全是,文件没有关闭“一旦最后一个字符被读取”,至少通常不会,它在读取期间处于半关闭状态,IO-manager/runtime下次执行此类操作时将关闭它。如果您正在快速打开和读取文件,如果操作系统限制不是太高,那么该延迟可能会导致您用完文件句柄。
    然而,对于大多数用例(以我有限的经验)来说,关闭文件句柄是足够及时的。 [有些人不同意,认为惰性 IO 在所有情况下都极其危险。它肯定有陷阱,但 IMO 的危险往往被夸大了。]

    So, can I just invoke readFile without closing the file handle myself?


    是的,当您使用 readFile 时,当文件内容被完全读取或注意到文件句柄不再被引用时,文件句柄会自动关闭。

    Will the handle stay open as long as I have not consumed (visited) the whole result string?


    不完全是, readFile将文件句柄置于半关闭状态,如 hGetContents 的文档中所述:

    Computation hGetContents hdl returns the list of characters corresponding to the unread portion of the channel or file managed by hdl, which is put into an intermediate state, semi-closed. In this state, hdl is effectively closed, but items are read from hdl on demand and accumulated in a special list returned by hGetContents hdl.


    foo :: String -> IO String
    foo filename = do
    s <- readFile "t.txt"
    putStrLn "File has been read."
    return s
    啊,那是另一端惰性 IO 的陷阱之一。此处文件在其内容被读取之前关闭。当 foo返回,文件句柄不再被引用,然后关闭。 foo 的消费者s 结果会发现 s是一个空字符串,因为当 hGetContents试图从文件中实际读取,句柄已经关闭。
    我混淆了 readFile 的行为与那个
    bracket (openFile file ReadMode) hClose hGetContents
    那里。 readFile仅在 s 之后关闭文件句柄不再被引用,因此它的行为与此处预期的一样正确。

    When the putStrLn is executed, I would (intuitively) expect that

    1. s contains the whole content of file t.txt,
    2. The handle used to read the file has been closed.

    不, s除了可能从文件句柄中获取一些字符的配方之外,它还没有包含任何内容。文件句柄是半封闭的,但不是封闭的。文件内容全部读完后关闭,或 s超出范围。

    If this is not the case:

    • What does s contain when putStrLn is executed?
    • In what state is the file handle when putStrLn is executed?
    • If when putStrLn is executed s does not contain the whole content of the file, when will this content actually be read, and when will the file be closed?

    前两个问题已经回答了,第三个问题的答案是“内容被消费时会读取文件”,当内容全部被读取或不再被引用时会关闭。
    上面的 bracket 会有所不同调用 - bracket保证最后的操作,这里是 hClose即使其他操作抛出异常也会运行,因此通常建议使用它。但是, hClosebracket 时运行返回,然后 hGetContents无法从现在真正关闭的文件句柄中获取任何内容。但是 readFile如果发生异常,不一定会关闭文件句柄。
    这是惰性 IO 的危险或怪癖之一,文件在需要其内容之前不会被读取,如果你错误地使用惰性 IO,那就太晚了,你不会得到任何内容。
    这是一个很多人(甚至大多数人)一次又一次陷入的陷阱,但是在被它咬住之后,人们很快就会知道什么时候 IO 需要非懒惰并且在这些情况下非懒惰地去做。
    替代方案(迭代器、枚举器、管道、管道……)避免了这些陷阱[除非实现者犯了错误],但在惰性 IO 完全没问题的情况下使用起来就不太好用了。另一方面,他们更好地处理不希望懒惰的情况。

    关于haskell - 读取文件后 Haskell 文件会自动关闭吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13868516/

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