Я написал небольшую программу Haskell для печати контрольных сумм MD5 всех файлов в текущем каталоге (рекурсивно поиск). В основном версия Haskell md5deep
. Все отлично и dandy, за исключением случаев, когда в текущем каталоге имеется очень большое количество файлов, и в этом случае я получаю ошибку, например:
<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
Изменить: У меня есть много файлов, которые не вписываются в ОЗУ, поэтому я не ищу решение, которое сразу считывает весь файл.