如何从haskell中的文件中读取二进制数据数组?

时间:2014-12-03 20:41:50

标签: haskell

尝试读取Word8的二进制文件,我有以下程序:

import qualified Data.Binary as B
type Chars = [B.Word8]

printChars :: Chars -> IO()
printChars cs = mapM_ print cs

main :: IO()
main = do
  chars <- B.decodeFile "chars"
  printChars chars

当我运行它时,我收到一个错误:

$ ./test
test: too few bytes. Failed reading at byte position 241

似乎decodeFile期待无限列表。 我怎么能告诉它只读尽可能多的元素?

编辑:

以下是我正在寻找的代码:(这适用于任何类型,而不仅仅是Word8。)

import Prelude hiding ( readFile )
import Data.ByteString.Lazy ( readFile )
import Data.Binary.Get ( isEmpty, runGet )
import qualified Data.Binary as B

type Chars = [B.Word8]

printChars :: Chars -> IO()
printChars cs = mapM_ print cs

-- see http://hackage.haskell.org/package/binary-0.7.1.0/docs/Data-Binary-Get.html
-- function getTrades
getChars = do
  e <- isEmpty
  if e then return []
  else do
    c <- B.get
    cs <- getChars
    return (c:cs)

main :: IO()
main = do
  input <- readFile "chars"
  printChars $ runGet getChars input

1 个答案:

答案 0 :(得分:4)

Data.Binary用于以规范方式(由Binary类实例定义)序列化已知类型。通常,它不适用于非结构化数据。

在您提供给我们的情况下,您尝试将文件中的字节反序列化为[B.Word8]类型的对象。如果您查看Data.Binary源代码,则可以看到以下内容

instance Binary a => Binary [a] where
    get    = do n <- get :: Get Int
            getMany n

这基本上意味着数组存储如下

[length of array, val1, val2, ....]

因此,当您将值应用于文件时,它会读取文件中的第一个Int(毫无疑问,这是一个非常大的数字),然后尝试读取该数量的值。

如果您只想将文件作为字节加载,则应使用Data.ByteString.getContents