1

我正在构建一个Conduit二进制文件,该文件由一个标头组成,后跟一个Double矩阵作为行排序列表。这是代码:

import Conduit ((.|), ConduitM, mapC, sinkFileBS, yield) 
import Control.Monad.Trans.Except (ExceptT) 
import Control.Monad.Trans.Resource (ResourceT) 
import Data.ByteString (ByteString) 
import Data.ByteString.Conversion (toByteString') 
import Data.Serialize.IEEE754 (putFloat64be) 
import Data.Serialize.Put (putListOf, runPut) 
import Data.Void (Void) 
import Numeric.LinearAlgebra.Data ((><), Matrix, toLists) 
import System.FilePath (FilePath) 

type FileWriter = ResourceT (ExceptT String IO) 

matrixSink :: FilePath -> ConduitM (Matrix Double) Void FileWriter ()
matrixSink path = byteBuilder .| sinkFileBS path where
  byteBuilder = do
    yield $ toByteString' "header" 
    mapC fromDoubleMatrix

fromDoubleMatrix :: Matrix Double -> ByteString
fromDoubleMatrix matrix = runPut $
   putListOf putFloat64be (concat toLists matrix)

这几乎可以工作。如果我使用

runExceptT . runConduitRes $ yield matrix .| matrixSink "test.dat"
  where matrix = (2 >< 2) [1, 2, 3, 4]

我得到了预期的文件,但在标题和双打列表之间有一个额外的字节。当使用show额外字节显示时,如下所示:

"\NUL\NUL\NUL\NUL\NUL\NUL\NUL\t"

知道如何不打印这个字节吗?或者如果它是一个规范的分隔符或其他东西(这样我可以在读者中忽略它)?

编辑:问题似乎发生putListOffromDoubleMatrix.

4

1 回答 1

1
putListOf :: Putter a -> Putter [a]
putListOf pa = \l -> do
  putWord64be (fromIntegral (length l))
  mapM_ pa l

putListOf在对单个列表元素进行编码之前对列表的长度进行编码。我想也许你正在处理固定的 2x2 矩阵,所以你不需要那个长度,你只想要:

fromDoubleMatrix :: Matrix Double -> ByteString
fromDoubleMatrix matrix = runPut $
   mapM_ putFloat64be (concat toLists matrix)
于 2017-11-03T15:13:33.127 回答