【问题标题】:withFile handle is empty [duplicate]withFile 句柄为空 [重复]
【发布时间】:2015-06-30 17:57:17
【问题描述】:

在我当前的工作目录中有一个名为test.txt 的文件,其中包含"Test\n"

使用System.IO.readFile,GHCI 返回内容:

Prelude System.IO> readFile "test.txt"
"Test\n"

但以下情况并非如此,在我看来应该是相等的:

Prelude System.IO> withFile "test.txt" ReadMode hGetContents
""

为什么不是这样?如何在 withFile IO 操作中获取整个文件内容?

【问题讨论】:

    标签: haskell io


    【解决方案1】:

    TL;DR:懒惰的 IO 是邪恶的。

    hGetContents 返回文件内容的 IO-lazy 列表。这意味着只有在实际访问所述列表时才会读取文件句柄。然后控制权传递给withFile 关闭文件句柄。最后,打印结果,并请求列表:现在才在句柄上执行读取。唉,太晚了。

    作为这种懒惰的丑陋手动“冲洗”,您可以尝试例如

    hGetCont handle = do
       c <- hGetContents handle
       length c `seq` return c
    

    上面强制计算列表的长度,因此强制读取整个文件。下面的 Reid Barton 提出了更漂亮的替代方案,避免使用可怕的邪恶惰性 IO。

    【讨论】:

    • 谢谢,但这仅回答了第一个问题。有没有办法消除这种懒惰?
    • @ominug,你不应该同时使用withFilehGetContents。使用readFile,或openFilehGetContents
    • @reid-barton 但是withFile可以使用什么呢?
    • 在 Haskell 中实现的惰性 IO 是邪恶的。 hGetContents 的概念并没有强迫它以这种方式实现。
    • 您不应手动关闭已传递给 hGetContents 的句柄(包括通过 withFile)(除非您确定您已经使用了尽可能多的文件) .如果你消费了整个文件,hGetContents 会自动为你关闭文件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多