写在Haskell中的文件的开头

Jac*_*cko 10 haskell file

我试图在文件的开头添加一个数字,但函数"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)

那么如何在文件的开头写一些东西呢?

Jav*_*ran 8

正如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 列表).对于玩具程序来说很好,但是如果你关心性能,你可以看看bytestringtext,具体取决于你的程序是处理字节还是文本(如果你想处理unicode文本).它们都比效率更高String.


Gab*_*aru 6

我设法让它工作,但我使用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仍然挂起文件的原因.

还有一个观察结果,如果你在此功能之前有另一个懒惰的读取,请用严格的版本替换它,因为你会再次遇到麻烦.