
On Thu, Oct 18, 2007 at 20:58:45 +1000, Matthew Brecknell wrote:
Magnus Therning:
hasEmpty s = let _first_empty = s !! 0 == '\n' _last_empty = (reverse s) !! 1 == '\n' in _first_empty || _last_empty
loadAndCheck fp = liftM hasEmpty $ readFile fp
main = getArgs >>= filterM loadAndCheck >>= mapM_ putStrLn The one problem I had was that running this on /all/ files in my WP resulted in an exception:
*** Exception: ./wp-includes/images/smilies/icon_mrgreen.gif: openFile: resource exhausted (Too many open files)
Is there some (easy) way to avoid this while still using readFile?
The perils of lazy IO: readFile closes its file descriptor only if it is is forced to read to end of file. Otherwise, you rely on the garbage collector to run the finaliser on the file handle sometime after it becomes unreachable, but since file handle exhaustion does not trigger garbage collection, there are no guarantees. See also the System.IO documentation.
For an extremely hackish (and untested) solution to your problem, replace the expression (_first_empty || _last_empty) with (_last_empty || _first_empty). If you can explain why that works, then you advance to the next level in your training!
I can see how that could have worked. Lazy thinking indeed :-) I wonder if the fact that it doesn't work should be considered a bug? Just to make sure I changed (broke) my code so that the very last character would be read (in case there is an almost crazy level of optimisation in ghc): _last_empty = (reverse s) !! 0 == '\n' Still no cigar :(
For a less hackish solution, you need to do a bit more work. Again, this is untested.
loadAndCheck fn = bracket (openFile fn ReadMode) hClose checkContents checkContents fh = do { s <- hGetContents fh; return $! hasEmpty s }
Note the explicit close, and "return $!" to ensure that hasEmpty has done its work before the file is closed.
Ah, `bracket` is a handy function to know! And it does work! /M -- Magnus Therning (OpenPGP: 0xAB4DFBA4) magnus@therning.org Jabber: magnus.therning@gmail.com http://therning.org/magnus