代码之家  ›  专栏  ›  技术社区  ›  jorgen

二进制文件写入程序添加额外字节

  •  1
  • jorgen  · 技术社区  · 7 年前

    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"
    

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

    编辑:问题似乎发生在 putListOf 施工 fromDoubleMatrix .

    1 回复  |  直到 7 年前
        1
  •  1
  •   NovaDenizen    7 年前
    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)
    
    推荐文章