2013-01-15 2 views
3

하스켈에서 바이너리 형식을 읽어야합니다. 형식은 매우 간단합니다. 데이터의 길이를 나타내는 네 개의 8 진수와 데이터가 이어집니다. 네 옥텟은 네트워크 바이트 순서의 정수를 나타냅니다.ByteString을 Int로 변환하고 endianness를 처리하는 방법은 무엇입니까?

4 바이트의 ByteString을 정수로 변환하려면 어떻게해야합니까? 나는 직접적인 캐스트 (C로, *(int*)&data이 될 것임)가 필요하다. 또한, 어떻게 엔디안에 대해 갈 수 있습니까? 직렬화 된 정수는 네트워크 바이트 순서이지만 시스템은 다른 바이트 순서를 사용할 수 있습니다.

Google 검색을 시도했지만 사전 순 전환에 대한 결과 만 표시됩니다.

답변

12

The binary package이 ByteStrings에서 다양한 크기와 엔디안 정수 타입을 얻기 위해 도구가 포함되어 있습니다.

+1

'runGet getWord32be의 bytes' 트릭을했다. –

3

폴드를 사용하고 foldl 또는 foldr을 사용하여 원하는 엔디안을 결정할 수 있다고 가정합니다 (어떤 것을 잊어 버렸습니다).

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

나는이 이진 연산자 작동합니다 생각 :

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

난 그냥 처음 4 바이트를 추출하고 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 
관련 문제