我正在尝试在文件的开头添加一个数字但函数" 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"
那么如何在文件的开头写一些东西呢?
答案 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,您的程序将在内存中保存所有文件内容(作为[]
的列表)。对于玩具程序,这很好,
但如果您关心性能,可以查看bytestring或text,具体取决于您的程序是处理字节还是文本(如果您想处理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
或其他一些方法来提高效率,但是您可以在块中进行复制,而不是需要将所有内容读入内存然后再将其吐出。我认为pipes
和conduit
都提供了应该让这更令人愉快的接口。