二进制文件编写器添加额外的字节
Binary file writer adds extra byte
我正在构建一个 Conduit
,它写入一个二进制文件,该文件包含一个 header 后跟一个 Double
矩阵作为一个 row-ordered 列表。这是代码:
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]
我得到了预期的文件,但在 header 和双打列表之间有一个额外的字节。当使用 show
显示时,额外的字节如下所示:
"\NUL\NUL\NUL\NUL\NUL\NUL\NUL\t"
知道如何不打印这个字节吗?或者如果它是规范的分隔符或其他东西(这样我就可以在 reader 中忽略它)?
编辑:问题似乎出现在 fromDoubleMatrix
中的 putListOf
构造中。
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)
我正在构建一个 Conduit
,它写入一个二进制文件,该文件包含一个 header 后跟一个 Double
矩阵作为一个 row-ordered 列表。这是代码:
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]
我得到了预期的文件,但在 header 和双打列表之间有一个额外的字节。当使用 show
显示时,额外的字节如下所示:
"\NUL\NUL\NUL\NUL\NUL\NUL\NUL\t"
知道如何不打印这个字节吗?或者如果它是规范的分隔符或其他东西(这样我就可以在 reader 中忽略它)?
编辑:问题似乎出现在 fromDoubleMatrix
中的 putListOf
构造中。
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)