2012-01-23 9 views
9

Mam plik zawierający [Double] zserializowany przez Data.Binary, który chciałbym odczytać za pomocą C. Oznacza to, że chcę napisać program w języku C, który odczytuje te dane do pamięci jako double[]. Planuję napisać program Haskella do deserializacji pliku danych, a następnie zapisać dane binarne w nowym, prostszym pliku, który mogę bezpośrednio odczytać w C, ale nie jestem pewien, jak napisać tylko surowe dane binarne (np. 8 bajtów dla podwójnego).Zapisywanie danych binarnych za pomocą Haskella do odczytu przez C?

Odpowiedz

3

Używanie Data.Binary do serializowania wartości Double lub Float nie jest dobre dla przenośności. Instancje Binary serializują wartości w postaci otrzymanej przez decodeFloat, tj. Jako mantysę i wykładnik. Mantysa jest serializowana jako Integer. Parsowanie jest niewygodne. Znacznie lepiej, jak już zasugerował ehird, jest użycie wariantu, który serializuje je jako wzorzec bitowy reprezentacji IEEE-754, oferowany przez cereal-ieee754 - jak ehird przypomniał mi, że został scalony (bez jakiejś konwersji między zmiennoprzecinkowym punktem i typy słów) do cereal - lub już wspomnianego data-binary-ieee754. Inną opcją jest serializowanie ich jako ciągi znaków przez show. Ma to tę zaletę, że unika problemów z endianizmem.

+0

Nawiasem mówiąc, funkcjonalność zboża-ieee754 została niedawno scalona w odpowiednie zboże. – ehird

+0

Ah, dzięki. Zapomniałem. Niestety, konwersje "Word64 <-> Double" i "Word32 <-> Float' zostały usunięte i są jedynymi rzeczami, którymi byłbym zainteresowany w obu pakietach;) –

+0

Tak, byłoby miło, gdyby te zostały podzielone na osobną paczkę na których mogą polegać biblioteki serializacyjne. – ehird

8

można ponownie wykorzystać do celów Data.Binary z pakietem data-binary-ieee754, co pozwala SZEREGOWANIE Float S i S, jak ich Double IEEE reprezentacji. Na przykład:

import Data.List 
import Data.Binary.Put 
import Data.Binary.IEEE754 
import Control.Monad 

putRawDoubles :: [Double] -> Put 
putRawDoubles xs = do 
    putWord64le $ genericLength xs 
    mapM_ putFloat64le xs 

Byłoby miło, gdyby nie było analogiem putWord64host dla Double sw na danych binarnych IEEE 754, ale ponieważ nie ma po prostu poszedł z little-endian. Jeśli chcesz być przenośny na różnych poziomach bez jawnej obsługi konwersji w twoim programie C, możesz spróbować putWord64host . doubleToWord (doubleToWord również z Data.Binary.IEEE754). Chociaż myślę, że endianness integers różni się od endianów zmiennoprzecinkowych na niektórych platformach ...

Nawiasem mówiąc, sugerowałbym użycie takiego formatu, nawet dla regularnej serializacji; Pętle IEEE są uniwersalne, a domyślny format zmiennoprzecinkowy binarny jest marnotrawny (jak zauważa Daniel Fischer).

Można również rozważyć bibliotekę serializacji cereal, która jest szybsza niż binarna, lepiej zarządzana (binarna nie była aktualizowana od 2009 r.) I ma obsługę formatu float IEEE built-in.

+1

Istnieje lub było bardzo mało platform z różnymi endianizmami typu float i integer. Zapomniałem które. Ale te bestie są zbyt rzadkie, by się nimi przejmować. –

Powiązane problemy