【发布时间】:2010-06-05 18:43:22
【问题描述】:
我编写了一个小型 Haskell 程序来打印当前目录中所有文件的 MD5 校验和(递归搜索)。基本上是 md5deep 的 Haskell 版本。一切都很好,除非当前目录有大量文件,在这种情况下,我会收到如下错误:
<program>: <currentFile>: openBinaryFile: resource exhausted (Too many open files)
似乎 Haskell 的懒惰导致它不关闭文件,即使在其相应的输出行完成之后也是如此。
相关代码如下。感兴趣的函数是getList。
import qualified Data.ByteString.Lazy as BS
main :: IO ()
main = putStr . unlines =<< getList "."
getList :: FilePath -> IO [String]
getList p =
let getFileLine path = liftM (\c -> (hex $ hash $ BS.unpack c) ++ " " ++ path) (BS.readFile path)
in mapM getFileLine =<< getRecursiveContents p
hex :: [Word8] -> String
hex = concatMap (\x -> printf "%0.2x" (toInteger x))
getRecursiveContents :: FilePath -> IO [FilePath]
-- ^ Just gets the paths to all the files in the given directory.
有什么想法可以解决这个问题吗?
整个程序都在这里:http://haskell.pastebin.com/PAZm0Dcb
编辑:我有很多文件不适合 RAM,所以我不是在寻找将整个文件一次读入内存的解决方案。
【问题讨论】:
-
fwiw 我为这类事情写了一个小模块目录树 (hackage.haskell.org/package/directory-tree),尽管我认为你大部分是在你的代码中重写它:)