我试图在文件的开头添加一个数字,但函数"appendFile"添加在文件的末尾.
我写了这个,但它没有用.
myAppendFile file = do x <- readFile file
writeFile file "1"
appendFile file x
return x
Run Code Online (Sandbox Code Playgroud)
当我做:
*main> myAppendFile "File.txt"
Run Code Online (Sandbox Code Playgroud)
错误是
the ressource is busy (file is locked)
Run Code Online (Sandbox Code Playgroud)
那么如何在文件的开头写一些东西呢?
正如Gabriel指出的那样,问题在于readFile按需读取文件内容,并且仅在文件内容被完全消耗时才关闭底层文件句柄.
解决方案是要求完整的文件内容,以便处理程序在执行之前关闭writeFile.
简答:使用严格包中的readFile.
import qualified System.IO.Strict as SIO
import Data.Functor
myAppendFile :: FilePath -> IO String
myAppendFile file = do
x <- SIO.readFile file
writeFile file "1"
appendFile file x
return x
main :: IO ()
main = void $ myAppendFile "data"
Run Code Online (Sandbox Code Playgroud)
实现此目的的另一个简单"黑客"是使用seq:
myAppendFile :: FilePath -> IO String
myAppendFile file = do
x <- readFile file
length x `seq` writeFile file "1"
appendFile file x
return x
Run Code Online (Sandbox Code Playgroud)
seq a b基本上只是b加上需要的时候b,a(length x在这种情况下)在审查之前被评估为WHNFb,这是因为length需要x遍历其参数(在这种情况下),直到[]可以看到空列表,因此需要完整的文件内容.
请记住,通过使用严格的IO,您的程序将保存Char内存中的所有文件内容(作为s 列表).对于玩具程序来说很好,但是如果你关心性能,你可以看看bytestring或text,具体取决于你的程序是处理字节还是文本(如果你想处理unicode文本).它们都比效率更高String.
我设法让它工作,但我使用ByteString这是一个严格的数据类型:
import Data.ByteString.Char8 as B
myAppendFile file = do
x <- B.readFile file
B.writeFile file $ B.pack "1"
B.appendFile file x
return $ B.unpack x
main = myAppendFile "c:\\test.txt"
Run Code Online (Sandbox Code Playgroud)
由于Haskell的懒惰,你的代码给了你这个错误.当您尝试在文件中写入内容时,数据未完全读出,x因为haskell x在该代码点之前不需要值.这就是为什么Haskell仍然挂起文件的原因.
还有一个观察结果,如果你在此功能之前有另一个懒惰的读取,请用严格的版本替换它,因为你会再次遇到麻烦.