如何关闭haskell中的文件

时间:2014-03-04 08:46:49

标签: file haskell

我有一个haskell问题... 我在haskell中打开一个文件,之后我想在该文件中添加一些文本。

ame :: IO ()

ame = do
    putStr "Enter the file name: "
    name <- getLine
    file <- readFile name
    putStrLn "Do you want to add new records? "
    question <- getLine
    if question == "yes" then do
        putStrLn "Enter your records:"
        newRec <- getLine
        file <- writeFile name (file ++ newRec)

        putStrLn "a"
    else
        putStr "b"

这是我的代码。当我想在我的文件中添加(写入)新内容时,我收到此错误... “openFile:资源忙(文件被锁定)”。 我怎么能解决这个问题?我被告知这是因为我没有关闭文件..但我怎么能关闭它?

2 个答案:

答案 0 :(得分:6)

函数readFile使用了“懒惰IO”,这是Haskell语言的一个有争议的特性(注意:“懒惰IO”与“懒惰评估”不同)。

当您说file <- readFile name时,此时实际上并未读取该文件。相反,一旦您评估结果字符串file,就会读取该文件。扫描您的计划时,我们发现您评估file的位置仅在此处:

file <- writeFile name (file ++ newRec)

函数writeFile没有返回任何内容,所以你的意思可能就是这样:

writeFile name (file ++ newRec)

当您尝试编写相同的文件时,您正在阅读名为name的文件。这就是造成文件锁定异常的原因。

解决方案1(推荐)

只是使用适当的函数,而不是读取和写入整个文件只是为了追加一些东西:

appendFile :: FilePath -> String -> IO ()

表现得像writeFile,但追加到最后。无需先读取文件。您的代码变为:

ame = do
    putStr "Enter the file name: "
    name <- getLine
    putStrLn "Do you want to add new records? "
    question <- getLine
    if question == "yes" then do
        putStrLn "Enter your records:"
        newRec <- getLine
        appendFile name newRec
        putStrLn "a"
    else
        putStr "b"

解决方案2(临时修复)

您还可以通过确保在写入文件之前评估整个文件内容来防止出现此问题。然后,在开始写入之前,文件将在阅读后关闭。有几种方法可以做到这一点。这是一个:

import Control.DeepSeq
import Control.Exception

ame :: IO ()
ame = do
    putStr "Enter the file name: "
    name <- getLine
    file <- readFile name
    evaluate (force file)
    putStrLn "Do you want to add new records? "
    question <- getLine
    if question == "yes" then do
        putStrLn "Enter your records:"
        newRec <- getLine
        file <- writeFile name (file ++ newRec)
        putStrLn "a"
    else
        putStr "b"

重要的新行是evaluate (force file),这会导致此时评估file的全部内容。

答案 1 :(得分:0)

writeFile返回IO()http://www.haskell.org/hoogle/?hoogle=writeFile

writeFile name (file ++ newRec)

只做file <-

您也不需要在readFile之后关闭文件,只需在执行openFile后关闭文件,然后您必须执行hClose file