用Haskell写二进制数据以便由C读取?

时间:2012-01-23 00:16:20

标签: c serialization haskell binary

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

2 个答案:

答案 0 :(得分:8)

您可以使用data-binary-ieee754包重用Data.Binary,这样可以将FloatDouble序列化为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

如果在data-binary-ieee754中有putWord64host的{​​{1}}类似物会很好,但是因为不存在我只是使用little-endian。如果您希望在没有明确处理C程序中的转换的情况下跨端点移植,可以尝试DoubleputWord64host . doubleToWord也来自doubleToWord)。虽然我认为整数字节序在某些平台上与浮点字节序不同......

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

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

答案 1 :(得分:3)

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