Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading sequence of ints from a binary file

I have a binary file containing a sequence of 32-bit ints. How do I go about reading them into an list (or Data.Array, which I'll probably end up using)?

All I can find in the documentation is this hGetBuf function, and it isn't clear how to go about use it (requires a Ptr to a buffer?). http://www.haskell.org/ghc/docs/latest/html/libraries/base-4.3.1.0/System-IO.html#v:hGetBuf

Surely there must be a simple approach, but I can't find it!

like image 376
oadams Avatar asked Jun 09 '11 12:06

oadams


2 Answers

If the file is just 32-bit ints, then heed @TomMD's warning. Something like this should do the job.

import Control.Applicative
import Control.Monad
import Data.Binary
import Data.Binary.Get
import Data.Binary.Put
import qualified Data.ByteString.Lazy as BL
import qualified Data.ByteString as BS
import Data.Int
import System.Posix

testPut = BL.writeFile "foo.bin" . runPut . mapM_ put $ nums
  where nums :: [Int32]
        nums = [5,6,7,8]

testGet :: IO [Int32]
testGet = do n <- fromInteger . toInteger . fileSize <$> getFileStatus "foo.bin"
             let readInts = runGet (replicateM (n `div` 4) get)
             readInts . BL.fromChunks . (:[]) <$> BS.readFile "foo.bin"
like image 142
Anthony Avatar answered Nov 11 '22 03:11

Anthony


You can do this quite easily with the binary package. You can find the file-reading documentation here.

It already includes a way to deserialize a list of 32-bit integers, so you would just need to do call the decodeFile function. You may want to have a typed-version of it for clarity:

decodeIntsFile :: FilePath -> IO [Int32]
decodeIntsFile = decodeFile

Then if you want your list of integers as an array, use the appropriate array conversion, such as listArray.

like image 32
ScottWest Avatar answered Nov 11 '22 03:11

ScottWest