我有一个包含由Data.Binary序列化的[Double]
的文件,我想用C读取。也就是说,我想编写一个C程序,将该数据作为{{1}读入内存}。我打算编写一个Haskell程序来反序列化数据文件,然后将二进制数据写入一个新的,更简单的文件,我可以直接读入C,但我不知道如何写出原始的二进制数据(例如,双倍的8个字节)。
答案 0 :(得分:8)
您可以使用data-binary-ieee754包重用Data.Binary
,这样可以将Float
和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
如果在data-binary-ieee754中有putWord64host
的{{1}}类似物会很好,但是因为不存在我只是使用little-endian。如果您希望在没有明确处理C程序中的转换的情况下跨端点移植,可以尝试Double
(putWord64host . doubleToWord
也来自doubleToWord
)。虽然我认为整数字节序在某些平台上与浮点字节序不同......
顺便提一下,我建议使用这样的格式,即使是常规序列化也是如此; IEEE浮点数是通用的,二进制的默认浮点格式是浪费的(正如Daniel Fischer所指出的那样)。
您可能还需要考虑cereal序列化库,它比二进制文件更快,维护得更好(二进制文件自2009年以来未更新)并且支持IEEE浮点格式built-in。 / p>
答案 1 :(得分:3)
使用Data.Binary
序列化Double
或Float
值并不具备可移植性。 Binary
实例将decodeFloat
获得的格式中的值序列化,即作为尾数和指数。尾数序列化为Integer
。解析不方便。正如ehird已经建议的那样,更好的是使用一种变体,将它们序列化为IEEE-754表示的位模式,由cereal-ieee754提供 - 正如ehird提醒我的那样,已合并(减去一些)将浮点数和单词类型转换为cereal - 或已经提到的data-binary-ieee754。另一个选项是通过show
将它们序列化为字符串。这有利于避免任何字节序问题。