[Haskell-beginners] problem with lazy IO
Dennis Raddle
dennis.raddle at gmail.com
Wed Nov 9 18:12:20 CET 2011
I have the following code, which reads several thousand text files and
creates some Map data. On Windows XP, it crapped out with the error
"resource exhausted: too many open files." So I'm sure I need to make it
stricter. I've never tried to do that before, so I'm not sure where the
strictness is necessary. Maybe all I need is to switch to strict
ByteStrings?
-- Read a bunch of text files. The files are organized in pairs, where the
file names in each pair are
-- "a<number>.txt" and "f<fnumber>.txt". Example: "a00001.txt" and
"f00001.txt".
-- Each file is a list of float values specified in a certain text format
(which happens to be
-- an output format of the audio-related program Csound)
--
-- Input:
-- [(String,String)] : a list of pairs of file names
-- String : directory in which the files exist
readPvsFiles :: [(String,String)] -> String -> IO (Map Int (Map Float
Float))
readPvsFiles filenames dir = do
-- contents :: [(Int,Map Float Float)]
-- where Int is the number in the file name.
-- and Map Float Float is a map of numbers in the
-- in the first file mapped to numbers in the second file
contents <- mapM (oneFilePair dir) filenames
return $ M.fromList contents
-- Read one file pair.
--
-- Input:
-- String : directory of the files
-- (String,String) : the two file names in the pair
-- (Int,Map Float Float) :
-- Int is the number in the file name.
-- and Map Float Float is a map of numbers in the
-- in the first file mapped to numbers in the second file
oneFilePair :: String -> (String,String) -> IO (Int,Map Float Float)
oneFilePair dir (ffile,afile) = do
-- Read the float values from each file (which is a list of floats in
-- a text format.
fvalues <- readTableValues (dir ++ "/" ++ ffile)
avalues <- readTableValues (dir ++ "/" ++ afile)
-- t is the number in the filename.
let t = read . take 6 . drop 1 $ ffile
return (t, M.fromList $ zip fvalues avalues)
-- Open the file via readFile, and parse all the text values in it.
readTableValues :: String -> IO [Float]
readTableValues s = do
b <- readFile s
let bs = lines b
lenLine = head . drop 1 $ bs
n = read (drop 6 lenLine) :: Int
-- valueLines :: [String]. This is a list of the lines
-- in the file that have the float values. One float
-- value in text format per line.
valueLines = take n . drop 25 $ bs
return $ map read valueLines
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/beginners/attachments/20111109/b0e09ab0/attachment.htm>
More information about the Beginners
mailing list