损坏的用户、损坏的数据.二进制文件或损坏的安装



我正在尝试使用 Data.Binary 来序列化地图,但我得到一个错误:没有足够的字节。然后,我尝试使一个更简单的示例使用整数列表,在这里,这也不起作用。可能有什么问题?我的代码中是否有错误,我误解了什么,或者我的安装可能存在问题,在这种情况下,我该如何解决?

以下是我的测试代码...

import Data.Binary
worldfile = "binarysimple.world"
main = do
  ser <- decodeFileOrFail worldfile
  case ser of
       Right w -> showWorld $ show (w :: [Int]) 
       Left (_,s) -> putStrLn ("the error:"++s) >> newworld
newworld = do
  let world = [1,2,3] :: [Int]
  showWorld $ show world 
  encodeFile worldfile $ encode world
showWorld = putStrLn

。以及运行它时的输出:

ghci binarysimple.hs
GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
[1 of 1] Compiling Main             ( binarysimple.hs, interpreted )
Ok, modules loaded: Main.
*Main> main
Loading package array-0.4.0.1 ... linking ... done.
Loading package deepseq-1.3.0.1 ... linking ... done.
Loading package containers-0.5.0.0 ... linking ... done.
Loading package bytestring-0.10.0.2 ... linking ... done.
Loading package binary-0.7.1.0 ... linking ... done.
the error:demandInput: not enough bytes
[1,2,3]
*Main> newworld
[1,2,3]
*Main> main
the error:demandInput: not enough bytes
[1,2,3]
*Main> newworld
[1,2,3]
*Main>
Leaving GHCi.
$ ls -l binarysimple.world
-rw-r--r--  1 btobias  staff  40  8 Sep 21:15 binarysimple.world

我不知道确切的格式,但这可能是合理的输出:

$ hexdump -C binarysimple.world
00000000  00 00 00 00 00 00 00 20  00 00 00 00 00 00 00 03  |....... ........|
00000010  00 00 00 00 00 00 00 01  00 00 00 00 00 00 00 02  |................|
00000020  00 00 00 00 00 00 00 03                           |........|
00000028

问题

让我们回顾一下您认为自己在做什么以及正在做什么。

认为您正在使用binaryInt列表进行编码,并将该字节串写入文件。 然后,您从文件中读取并解码Int列表,结果却失败了。

您实际要做的是将Int的列表编码为字节串,然后将该字节串编码为字节串(因此,在字节前面附加了一个额外的长度字段)并将该字节串写入磁盘。 然后,您的解码失败,因为您在磁盘上有encode(encode(list))而不是encode(list)

解决方案

只需更改行读数:

encodeFile worldfile $ encode world

encodeFile worldfile world

阅读十六进制

00000000  00 00 00 00 00 00 00 20  00 00 00 00 00 00 00 03  |....... ........|
00000010  00 00 00 00 00 00 00 01  00 00 00 00 00 00 00 02  |................|
00000020  00 00 00 00 00 00 00 03

因此,上面的十六进制转储可以读取为一系列 64 位整数:0x20、3、1、2、3。 第一个值十进制 32 是 Bytestring 编码的一部分,指示剩余字节串(8 字节 * 4 个整数)的长度。 第二个值 3 是列表编码的一部分 - 它表示列表的长度。 最终值是列表的各个元素。

最后,你不需要一些随机的在线人向你解释格式,你可以从binary包中的实例中读取格式(一旦你足够熟悉Haskell)。

最新更新