【问题标题】:how do I read a 24 bit int of out of a haskell bytestring?如何从 haskell 字节串中读取 24 位 int?
【发布时间】:2011-06-04 20:03:50
【问题描述】:

我正在尝试使用 Haskell 解析二进制格式 (PES):

import qualified Data.ByteString.Lazy as BL
import Data.Word
import Data.Word.Word24
import qualified Data.ByteString.Lazy.Char8 as L8

data Stitch = MyCoord Int Int deriving (Eq, Show)

data PESFile = PESFile {
      pecstart :: Word24
    , width :: Int
    , height :: Int
    , numColors :: Int
    , header :: String
    , stitches :: [Stitch]
    } deriving (Eq, Show)


readPES :: BL.ByteString -> Maybe PESFile
readPES bs =
        let s = L8.drop 7 bs
            pecstart = L8.readInt s in
            case pecstart of
        Nothing -> Nothing
        Just (offset,rest) ->   Just (PESFile offset 1 1 1 "#PES" [])

main = do
  input <- BL.getContents
  print $ readPES input

我需要读取 pecstart 以获取其他数据的偏移量(宽度、高度和针迹) 但这对我不起作用,因为我需要读取 24 位值,而 ByteString 包似乎没有 24 位版本。

我应该使用不同的方法吗? Data.Binary 包似乎适用于简单格式,但我不确定它如何用于这样的事情,因为您必须读取一个值才能找到文件中其他数据的偏移量。我错过了什么?

【问题讨论】:

  • 你不会为PESFile 添加一个Binary 的实例吗?二进制包看起来没问题,因为 put/get 函数是一系列操作(例如,您可以读取 pecstart 以获取下一位)。
  • 我很想尝试这种方法 Jeff。我一直在研究关于二进制输入的 Real World Haskell 章节。如果有关于创建新二进制实例的教程,我很乐意试一试。
  • 出于效率原因,您可能应该将标头保留为字节串。并且MyCoord 应该使用严格的Int 字段(例如!Int)。
  • 如果您要使用 24 位整数做大量工作,我建议您查看 word24 包,hackage.haskell.org/package/word24。它提供了 24 位有符号和无符号整数,具有适当的边界、位移等。还有一个可存储的实例,但对于仅从字节串中读取一个值,我可能会使用 Don Stewart 的解决方案。

标签: haskell binary bytestring


【解决方案1】:

好吧,您可以通过索引 3 个字节(此处按网络顺序)来解析 24 位值:

import qualified Data.ByteString as B
import Data.ByteString (ByteString, index)
import Data.Bits
import Data.Int
import Data.Word

type Int24 = Int32

readInt24 :: ByteString -> (Int24, ByteString)
readInt24 bs = (roll [a,b,c], B.drop 3 bs)
   where a = bs `index` 0
         b = bs `index` 1
         c = bs `index` 2

roll :: [Word8] -> Int24
roll   = foldr unstep 0
  where
    unstep b a = a `shiftL` 8 .|. fromIntegral b

【讨论】:

  • 谢谢唐!乍一看,这看起来像是源代码,但后来我能够将它拼凑在一起,除了按位或,这是 hoogle 帮我解决的。
  • sourcery 是“魔术代码”有史以来最好的无意双关语。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-04-17
  • 2018-08-07
  • 2011-11-01
  • 2021-07-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多