【问题标题】:How to convert a ByteString to an Int and dealing with endianness?如何将 ByteString 转换为 Int 并处理字节序?
【发布时间】:2013-01-15 10:29:55
【问题描述】:

我需要在 Haskell 中读取二进制格式。格式相当简单:四个八位字节表示数据的长度,然后是数据。四个八位字节代表网络字节序中的一个整数。

如何将四个字节的ByteString 转换为整数?我想要一个直接转换(在 C 中,那将是 *(int*)&data),而不是字典转换。另外,我将如何处理字节顺序?序列化的整数是网络字节序,但机器可能使用不同的字节序。

我尝试了谷歌搜索,但是关于字典转换的结果只有旧的。

【问题讨论】:

    标签: haskell endianness bytestring


    【解决方案1】:

    The binary package 包含从 ByteStrings 获取各种大小和字节序的整数类型的工具。

    λ> :set -XOverloadedStrings
    λ> import qualified Data.Binary.Get as B
    λ> B.runGet B.getWord32be "\STX\SOH\SOH\SOH"
    33620225
    λ> B.runGet B.getWord32be "\STX\SOH\SOH\SOHtrailing characters are ignored"
    33620225
    λ> B.runGet B.getWord32be "\STX\SOH\SOH" -- remember to use `catch`:
    *** Exception: Data.Binary.Get.runGet at position 0: not enough bytes
    CallStack (from HasCallStack):
      error, called at libraries/binary/src/Data/Binary/Get.hs:351:5 in binary-0.8.5.1:Data.Binary.Get
    

    【讨论】:

      【解决方案2】:

      我假设您可以使用折叠,然后使用 foldlfoldr 来确定您想要哪个字节序(我忘了哪个是哪个字节序了)。

      foldl :: (a -> Word8 -> a) -> a -> ByteString -> a
      

      我认为这适用于二元运算符:

      foo :: Int -> Word8 -> Int
      foo prev v = (prev * 256) + v
      

      【讨论】:

        【解决方案3】:

        我只需提取前四个字节并使用Data.Bits 中的函数将它们合并为一个 32 位整数:

        import qualified Data.ByteString.Char8 as B
        import Data.Char (chr, ord)
        import Data.Bits (shift, (.|.))
        import Data.Int (Int32)
        
        readInt :: B.ByteString -> Int32
        readInt bs = (byte 0 `shift` 24)
                     .|. (byte 1 `shift` 16)
                     .|. (byte 2 `shift` 8)
                     .|. byte 3
                where byte n = fromIntegral $ ord (bs `B.index` n)
        
        sample = B.pack $ map chr [0x01, 0x02, 0x03, 0x04]
        main = print $ readInt sample -- prints 16909060
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-02-07
          • 2016-07-18
          • 2016-03-04
          • 2016-02-20
          • 1970-01-01
          相关资源
          最近更新 更多