Haskell lazy I/O and closing files

前端 未结 7 805
攒了一身酷
攒了一身酷 2020-12-07 23:35

I\'ve written a small Haskell program to print the MD5 checksums of all files in the current directory (searched recursively). Basically a Haskell version of md5deep

相关标签:
7条回答
  • 2020-12-08 00:05

    You don't need to use any special way of doing IO, you just need to change the order in which you do things. So instead of opening all files and then processing the content, you open one file and print one line of output at a time.

    import Data.Digest.Pure.MD5 (md5)
    import qualified Data.ByteString.Lazy as BS
    
    main :: IO ()
    main = mapM_ (\path -> putStrLn . fileLine path =<< BS.readFile path) 
       =<< getRecursiveContents "."
    
    fileLine :: FilePath -> BS.ByteString -> String
    fileLine path c = hash c ++ " " ++ path
    
    hash :: BS.ByteString -> String 
    hash = show . md5
    

    BTW, I happen to be using a different md5 hash lib, the difference is not significant.

    The main thing that is going on here is the line:

    mapM_ (\path -> putStrLn . fileLine path =<< BS.readFile path)
    

    It's opening a single file, it's consuming the whole content of the file and printing one line of output. It closes the file because it's consuming the whole content of the file. Previously you were delaying when the file was consumed which delayed when the file was closed.

    If you are not quite sure if you are consuming all the input but want to make sure the file gets closed anyway, then you can use the withFile function from System.IO:

    mapM_ (\path -> withFile path ReadMode $ \hnd -> do
                      c <- BS.hGetContents hnd
                      putStrLn (fileLine path c))
    

    The withFile function opens the file and passes the file handle to the body function. It guarantees that the file gets closed when the body returns. This "withBlah" pattern is very common when dealing with expensive resources. This resource pattern is directly supported by System.Exception.bracket.

    0 讨论(0)
提交回复
热议问题