写在Haskell中的文件的开头

时间:2015-05-13 17:40:06

标签: file haskell

我正在尝试在文件的开头添加一个数字但函数" appendFile"添加到文件的末尾。

我写了这个,但它没有用。

subjectInfo.subject_title = model.subject_title;
subjectInfo.subject_description = model.subject_description;
db.SaveChanges();

当我这样做时:

myAppendFile file = do x <- readFile file
                   writeFile file "1"
                   appendFile file x
                   return x

错误是

*main> myAppendFile "File.txt"

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

3 个答案:

答案 0 :(得分:8)

正如Gabriel指出的那样,问题是ViewGroups按需读取文件内容,并且只有在文件内容被完全消耗时它才会关闭底层文件句柄。

解决方案是要求完整的文件内容,以便在执行readFile之前关闭处理程序。

简短回答:使用严格包裹中的readFile

writeFile

实现此目的的另一个简单“黑客”是使用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"

seq

myAppendFile :: FilePath -> IO String myAppendFile file = do x <- readFile file length x `seq` writeFile file "1" appendFile file x return x 基本上只是seq a b加上需要b时,b(在这种情况下为a)会被评估为WHNF在仔细检查length x之前,这是因为b需要遍历其参数(在这种情况下为length),直到可以看到空列表x,因此完整的文件内容被要求。

请记住,通过使用严格的IO,您的程序将在内存中保存所有文件内容(作为[]的列表)。对于玩具程序,这很好, 但如果您关心性能,可以查看bytestringtext,具体取决于您的程序是处理字节还是文本(如果您想处理unicode文本)。它们都比Char更有效率。

答案 1 :(得分: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"

由于Haskell的懒惰,你的代码给了你这个错误。 当您尝试在文件中写入内容时,数据未在x中完全读出,因为haskell在该代码点之前不需要x值。这就是Haskell仍然挂起文件的原因。

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

答案 2 :(得分:1)

传统的方法也适用于Haskell。创建一个新的临时文件,将旧文件中的字节流转换为临时文件,然后将临时文件移到旧文件上。您可以/应该使用ByteString或其他一些方法来提高效率,但是您可以在块中进行复制,而不是需要将所有内容读入内存然后再将其吐出。我认为pipesconduit都提供了应该让这更令人愉快的接口。