Reputation: 401
I'm learning Haskell and as first challenge I chose to write an implementation of Huffman coding, the algorithm is almost done, only the part of read and write the file to a byte file is missing. What I need to do is a way to write a file based on the binary string I build.
For example, If a read from a txt
file the following string Hello
, after the huffman algorithm, I get the following Map which map the symbol to his binary number as string
[
("H": "110"),
("e": "111"),
("l": "0"),
("o": "10")
]
And I need to replace that bytes in the readed string and write as Bytes that binary numbers to a file, I tried to use the ByteString package and the writeFile function, but the function write the binary numbers as plain text and not as Bytes.
So that way Hello
pass to be 110111010
that should be write as Bytes to a file.
Upvotes: 1
Views: 196
Reputation: 477666
You can write a string of '0'
s and '1'
s to a file with writeFile :: FilePath -> String -> IO ()
. For example:
main :: IO ()
main = writeFile "out.txt" "110111010"
You can also convert eight bits to a Word8
and then write the ByteString
to a file with the WriteFile :: FilePath -> ByteString -> IO ()
of the Data.ByteString
module:
import Data.ByteString(writeFile, pack)
import Data.Word(Word8)
writeWord8s :: [Word8] -> IO ()
writeWord8s = writeFile "out.txt" . pack
You can convert a list of Bool
s to Word8
s, but then this has to be a multiple of eight. You can for example "pad" it with 0
s (or 1
s, or something else), but it should be a multiple of eight:
import Data.Bool(bool)
import Data.Bits((.|.), shiftL)
import Data.Word(Word8)
toWord8 :: [Bool] -> Word8
toWord8 = foldl ((. bool 0 1) . (.|.) . (`shiftL` 1)) 0
pack8pad0 :: [Bool] -> [Word8]
pack8pad0 [] = []
pack8pad0 xs
| null ys = [toWord8 (y ++ replicate (8 - length y) False)]
| otherwise = toWord8 y : pack8pad0 ys
where (y, ys) = splitAt 8 xs
I leave mapping the input to a String
of '0'
s and '1'
s as an exercise.
Upvotes: 1