Parsing Haskell-解析二进制流
我是哈斯克尔的新手,所以我可能错过了一些非常简单的东西 我在解析结构化的二进制流时遇到了非常困难的问题。 二进制流有不同的和有条件的部分(比如一个字段,它决定有多少项跟在它后面(Parsing Haskell-解析二进制流,parsing,haskell,binary,bit,Parsing,Haskell,Binary,Bit,我是哈斯克尔的新手,所以我可能错过了一些非常简单的东西 我在解析结构化的二进制流时遇到了非常困难的问题。 二进制流有不同的和有条件的部分(比如一个字段,它决定有多少项跟在它后面(ncount),或者什么类型的消息跟在它后面(type) 为了得到一个简单的工作示例,我尝试解析这个假设的二进制结构: +----------------+---------------+-------------- | Magic (8 bits) | type (3 bits) | type message... +
ncount
),或者什么类型的消息跟在它后面(type
)
为了得到一个简单的工作示例,我尝试解析这个假设的二进制结构:
+----------------+---------------+--------------
| Magic (8 bits) | type (3 bits) | type message...
+----------------+---------------+--------------
Type 1:
+----------------+-------------+-------------+-----------------+
|ncount (3 bits) | n1 (3 bits) | n1 (3 bits) | nN (3 bits)... |
+----------------+-------------+-------------+-----------------+
Type 2:
+----------------+---------------+
| num1 (7 bits) | num2 (7 bits) |
+----------------+---------------+
...
到目前为止,我的代码是:
{-# LANGUAGE RecordWildCards #-}
module Main where
import Data.Bits
import Data.Binary as B
import qualified Data.Binary.Bits.Get as BG
import qualified Data.ByteString as BS
data Header = Header {
magic :: Word8
,mtype :: Word8
,num1 :: Word8
,num2 :: Word8
} deriving (Show)
--instance Show (Get Header) where
-- show (Header {..}) = show . magic
parse_header :: B.Get Header
parse_header = BG.runBitGet parse_header'
-- Example, assume type 2 for now
parse_header' :: BG.BitGet Header
parse_header' = do
magic <- BG.getWord8 8
mtype <- BG.getWord8 3
num1 <- BG.getWord8 7
num2 <- BG.getWord8 7
return $ Header magic mtype num1 num2
main :: IO ()
main = do
putStrLn "Start"
-- File containing binary stream
fstr <- BS.readFile "data/hbin.bin"
let header = parse_header
in
-- How do I print out Header?
print header
-- * No instance for (Show (Get Header))
-- arising from a use of `print'
-- * In the expression: print header
putStrLn "\nEnd"
显然,我计划递归地解析它,但现在我甚至看不到我读到的值
我已经遵循了,但它使用的是Data.Binary.Strict(Binary-Strict),它在Windows上不编译(至少在我的Windows上)
我也遵循了这一点,但它没有显示如何使用通过getWord8
获得的值(我是否需要将它们转换为Int以将其读取为十进制?)
同样,我是Haskell的新手,不熟悉Monads(我相信Get就是这样)。header=parse\u header
只是给解析器起了一个新名字。您需要一个函数来运行解析器(为了简单起见,这里选择runGet
,但您应该选择另一个函数,以便更轻松地处理错误情况):
请注意,它采用惰性的ByteString
(Data.ByteString.lazy
),而不是严格的(Data.ByteString
)
。。。
导入Data.ByteString.Lazy(toLazy)
...
main=do
fstr
* No instance for (Show (Get Header)) arising from a use of `print'
* In the expression: print header
runGet :: Get a -> ByteString -> a
...
import Data.ByteString.Lazy (toLazy)
...
main = do
fstr <- BS.readFile "data/hbin.bin"
let header = runGet parse_header (fromStrict fstr)
print header
putStrLn "End"