2012-01-23 57 views
9

我有一个文件,其中包含一个由Data.Binary序列化的[Double],我想用C读取它。也就是说,我想编写一个C程序,将该数据读取到内存中作为double[]。我打算编写一个Haskell程序来反序列化数据文件,然后将二进制数据写入一个新的,更简单的文件,我可以直接读入C,但我不确定如何只写出原始二进制数据(例如双字节为8个字节)。用Haskell写入二进制数据可以被C读取?

回答

3

使用Data.Binary来序列化DoubleFloat值对于可移植性来说不是很好。 Binary实例序列化由decodeFloat获得的形式的值,即作为尾数和指数。尾数序列号为Integer。解析不方便。正如eHird已经提出的,更好的是使用一个将它们序列化为IEEE-754表示的位模式的变体,如cereal-ieee754所提供的那样 - 正如ehird提醒的那样,已经合并(减去浮点和单词类型)转换为cereal - 或已经提到的data-binary-ieee754。另一个选项是通过show将它们序列化为字符串。这具有避免任何字节序问题的优点。

+0

顺便说一下,谷物ieee754的功能最近合并到谷物本身。 – ehird

+0

啊,谢谢。我忘了。不幸的是,'Word64 <-> Double'和'Word32 <-> Float'转换已被删除,并且它们是我在任一包中感兴趣的唯一东西;) –

+0

是的,如果将这些转换为单独的包序列化库可能依赖于。 – ehird

8

您可以重复使用Data.Binary用于data-binary-ieee754包,该包允许将序列化Float s和Double作为它们的IEEE表示。例如:

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 

这将是很好,如果有中putWord64hostDouble S IN数据二进制IEEE754模拟,但由于没有我只是小端去。如果您希望在C程序中无需明确处理转换就可以在字节码之间进行移植,则可以尝试putWord64host . doubleToWorddoubleToWord也是从Data.Binary.IEEE754)。虽然我认为整数字节序在一些平台上不同于浮点字节序列...

顺便提一句,我建议使用这样的格式,即使是你的常规序列化; IEEE浮点是通用的,而二进制的默认浮点格式是浪费的(正如Daniel Fischer所指出的那样)。

您可能还想考虑cereal序列化库,它比二进制更快,保持得更好(二进制文件自2009年以来未更新)并且支持IEEE浮点格式built-in

+1

有或有几个平台具有不同的浮点和整数字节序。我忘了哪个。但这些野兽太难以担忧了。 –