【问题标题】:"resource busy (file is locked)" error in HaskellHaskell 中的“资源繁忙(文件已锁定)”错误
【发布时间】:2011-02-19 19:52:11
【问题描述】:

我对 Haskell 很陌生。事实上,我正在通过this section of this tutorial. 我遇到了这段代码:

import System.IO     
import Data.Char  

main = do     
    contents <- readFile "girlfriend.txt"     
    writeFile "girlfriendcaps.txt" (map toUpper contents) 

读取名为“girlfriend.txt”的文件的内容并将该文件的大写版本写入名为“girlfriendcaps.txt”的新文件。

所以,我想稍微修改一下代码以获取要操作的文件名。我将代码更改为:

import System.IO
import Data.Char

main = do
    path <- getLine
    contents <- readFile path
    writeFile path (map toUpper contents)

现在,显然这里的主要区别是我正在读取和写入同一个文件。正如我现在正在考虑的那样,这一定是一个惰性评估的事情,但我收到了“资源繁忙”错误消息。如果我错了,请纠正我,但我猜 readFile 在 writeFile 询问文件内容之前不会开始读取文件。然后 writeFile 尝试写入文件,但它仍然必须打开文件,因为它也在询问内容。我在附近吗?

所以,真正的问题是:如何在 Haskell 中读取和写入同一个文件?这是有道理的,它更困难,因为您将写入与您经常读取的文件不同的文件,但是为了我自己的启发,您将如何读取和写入同一个文件?

【问题讨论】:

    标签: haskell


    【解决方案1】:

    确实,这是一个“懒惰的评价”。

    import System.IO
    import Data.Char
    
    main = do
        path <- getLine
        contents <- readFile path
        writeFile path (map toUpper contents)
    

    请记住,Haskell 在评估方面主要是惰性的,IO 子系统的大部分也是如此。因此,当您调用“readFile”时,您开始从文件中流式传输数据。当您立即调用“writeFile”时,您开始将字节流式传输回同一个文件

    这将是一个错误(即销毁您的数据),因此 Haskell 会锁定资源,直到它被完全评估,并且您会收到一个很好的错误消息。

    有两种解决方案:

    • 不要破坏性地覆盖文件,而是复制到新文件中
    • 或者,使用严格的 IO

    要使用严格的 IO,推荐使用 'text' 或 'strict' 包。

    【讨论】:

      【解决方案2】:

      您要查找的是如何在ReadWriteMode 中打开文件。

      fileHandle <- openFile "fileName.txt" ReadWriteMode
      contents <- hGetContents fileHandle
      

      在文件中向前和向后导航有些棘手。

      请参阅 RWH 的 Working with files and handles 和 System.IO 文档的 Operations on Handles

      【讨论】:

        【解决方案3】:

        完全取决于您要执行的操作。通常,在任何语言中,这可能都是一个糟糕的设计,因为如果程序内部或外部出现任何问题(例如用户错误),那么您已经破坏了原始数据并且无法重试。它还要求将整个文件保存在内存中,如果它只有几个字节,这很酷,但当有人决定在一个非常大的文件上运行它时就不那么好了。

        如果你真的想这样做,那么为输出生成一个临时文件名,然后一旦你知道你已经成功写入它,你就可以删除原始文件并重命名新文件。

        【讨论】:

          猜你喜欢
          • 2019-08-08
          • 2021-12-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-18
          相关资源
          最近更新 更多