2011-06-04 49 views
3

我試圖解析使用Haskell的二進制格式(PES):如何讀取haskell字符串中的24位整數?

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包對於簡單的格式似乎很好,但我不確定它是如何工作的,因爲你必須讀取一個值才能找到文件中其他數據的偏移量。我失蹤的東西?

+1

難道你不只是添加'Binary'爲'PESFile'的實例?二進制包看起來很好,因爲put/get函數是一系列操作(例如,您可以閱讀pecstart以獲得下一位)。 – 2011-06-04 20:09:03

+0

我很想嘗試這種方法傑夫。我一直在關於二進制輸入的Real World Haskell章節中工作。如果有關於創建新Binary實例的教程,我很樂意嘗試一下。 – nont 2011-06-04 20:14:44

+0

出於效率的原因,您應該將標題保留爲字符串。而'MyCoord'應該使用嚴格的'Int'字段(例如'!Int')。 – 2011-06-04 20:26:21

回答

5

那麼,你可以通過索引解析24位值了3個字節(這裏以網絡順序):

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 
+0

謝謝!乍看之下,這看起來像源源不斷,但隨後我可以將它拼湊在一起,除了按位或者哪一個哈格利幫助我。 – nont 2011-06-04 20:30:11

+1

sourcery是有史以來最好的無意雙關「魔法碼」。 – rampion 2011-06-04 22:27:25

+0

http://www.goodreads.com/book/show/34499.Sourcery – 2016-12-16 05:27:41

相關問題