我对Haskell很新.实际上,我正在完成本教程的这一部分. 我遇到了这段代码:
import System.IO
import Data.Char
main = do
contents <- readFile "girlfriend.txt"
writeFile "girlfriendcaps.txt" (map toUpper contents)
Run Code Online (Sandbox Code Playgroud)
其中读取名为"girlfriend.txt"的文件内容,并将文件的大写版本写入名为"girlfriendcaps.txt"的新文件中.
所以,我想稍微修改一下代码来取代文件的名称.我将代码更改为:
import System.IO
import Data.Char
main = do
path <- getLine
contents <- readFile path
writeFile path (map toUpper contents)
Run Code Online (Sandbox Code Playgroud)
现在,显然这里的主要区别在于我正在读取和写入同一个文件.正如我现在想的那样,这肯定是一个懒惰的评估,但我得到了"资源忙"的错误信息.如果我错了,请纠正我,但我想readFile不会开始读取文件,直到writeFile询问它的内容.然后writeFile尝试写入文件,但它仍然必须打开文件,因为它也要求内容.我在那附近吗?
所以,真正的问题是:如何在Haskell中读取和写入相同的文件?有意义的是,它更难,因为你会从你经常阅读的文件中写入不同的文件,但是对于我自己的启发,你会如何读写同一个文件?
Don*_*art 25
实际上,这是一个"懒惰的评价事物".
import System.IO
import Data.Char
main = do
path <- getLine
contents <- readFile path
writeFile path (map toUpper contents)
Run Code Online (Sandbox Code Playgroud)
请记住,Haskell在评估中主要是懒惰的,IO子系统也是如此.因此,当您调用'readFile'时,您开始从文件中传输数据.然后,当您立即调用"writeFile"时,您开始将字节流回到同一文件
这将是一个错误(即破坏您的数据),因此Haskell锁定资源,直到它被完全评估,并且您得到一个很好的错误消息.
有两种解决方案:
要使用严格的IO,建议使用"text"或"strict"包.
您正在寻找的是如何打开文件ReadWriteMode.
fileHandle <- openFile "fileName.txt" ReadWriteMode
contents <- hGetContents fileHandle
Run Code Online (Sandbox Code Playgroud)
在文件中向前和向后导航有一些比较棘手的东西.
请参阅使用 RWH中的文件和句柄,以及System.IO文档中的Handles上的Operations.
取决于你想要做什么.作为一项规则,在任何语言中,这可能是一个糟糕的设计,因为如果在程序内部或外部出现任何问题(例如用户错误),那么您已经销毁了原始数据,无法再次尝试.它还要求整个文件保存在内存中,如果它只有几个字节就很酷,但是当有人决定在一个非常大的文件上运行它时就不那么好了.
如果你真的想这样做,那么为输出生成一个临时文件名,然后一旦你知道你已成功写入它,你可以删除原始文件并重命名新文件.