如何关闭haskell中的文件

Sel*_*yst 3 haskell file

我有一个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"
Run Code Online (Sandbox Code Playgroud)

这是我的代码.当我想在我的文件中添加(写入)新内容时,我收到此错误..."openFile:resource busy(file is locked)".我怎么能解决这个问题?我被告知这是因为我没有关闭文件..但我怎么能关闭它?

kos*_*kus 6

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

当你说file <- readFile name,那时文件实际上没有被读取.而是在评估结果字符串后读取文件file.扫描您的程序,我们看到您评估的file地点仅在此处:

file <- writeFile name (file ++ newRec)
Run Code Online (Sandbox Code Playgroud)

该函数writeFile不会返回任何内容,因此您的实际意思可能是:

writeFile name (file ++ newRec)
Run Code Online (Sandbox Code Playgroud)

因此,name当您尝试编写同一文件时,您正在读取调用的文件.这就是造成文件锁定异常的原因.

解决方案1(推荐)

而不是只是读取和写入整个文件只是为了追加到最后,只需使用适当的函数:

appendFile :: FilePath -> String -> IO ()
Run Code Online (Sandbox Code Playgroud)

表现得像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"
Run Code Online (Sandbox Code Playgroud)

解决方案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"
Run Code Online (Sandbox Code Playgroud)

重要的新行是evaluate (force file)导致此时file评估整个内容.