2012-07-08 50 views
5

我正在实现一个协议,该协议规定表示密码的字符串应串行化为固定长度的10字节字段。我正在使用Data.Cereal来执行此任务。这是我最近去吧:使用Data.Cereal或Data.Binary对字符串进行序列化

padText :: Int -> Text -> Text 
padText fieldLen = T.justifyLeft fieldLen '\NUL' 

putPassword :: Putter Password 
putPassword = put . TE.encodeUtf8 . padText 10 

穿上字节串前添加一个额外的8字节块到它是什么编码制作的面前:

runPut $ putPassword "Friend" 

结果:

"\NUL\NUL\NUL\NUL\NUL\NUL\NUL\nFriend\NUL\NUL\NUL\NUL" 

我不想要额外的块。为什么这样表现?

有谁知道如何只序列化10个原始字节?

回答

7

我认为“额外的块”是指"\NUL\NUL\NUL\NUL\NUL\NUL\NUL\n的第一位。这是一个64位长的字段(注意它的值是10),它是ByteString的序列化定义的一部分。由于您在调用TE.encodeUtf8后已经有了一个字节串,我建议您只使用putByteString来避免长度字段(或者如果您导入惰性文本编码模块,则使用putLazyByteString)。

2

正如Thomas在ByteStrings上所说的put预先编码的长度。如下图所示 是实际的实例:

instance Serialize B.ByteString where 
    put bs = do put (B.length bs :: Int) 
       putByteString bs 
    ... 

单独putByteString没有。解决方案是使用putByteString

putPassword :: Putter Password 
putPassword = putByteString . TE.encodeUtf8 . padText 10