2013-09-08 3 views
3

Я пытаюсь использовать Data.Binary для сериализации карты, но у меня есть ошибка: недостаточно байт. Затем я попытался сделать более простой пример работы с списком целых чисел, здесь тоже не работает. Что может быть неправильным? Есть ли ошибка в моем коде, что-то я неправильно понял или может возникнуть проблема с моей установкой, и в этом случае, как мне ее решить?Сломанный пользователь, сломанный 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 

ответ

8

Проблема

Давайте рассмотрим, что вы думаете, что делаете и что делаете.

Вы считаете, что используете binary для кодирования списка Int и записи этого байта в файл. Затем вы читаете из файла и декодируете список из Int s только для того, чтобы он сработал.

Что вы на самом деле делаете, это кодирование списка Int s как bytestring, а затем кодирование того, что bytestring как bytestring (так, дополнительное поле длины добавляется к байтам) и записывает, что bytestring на диск. Затем ваш декодирование завершится неудачей, потому что у вас есть на диске encode(encode(list)) вместо encode(list).

Решение

Просто измените чтение строки:

encodeFile worldfile $ encode world 

к

encodeFile worldfile world 

Reading HexDump

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 бит i ntegers: 0x20, 3, 1, 2, 3. Первое значение, decimal 32, является частью кодировки Bytestring и указывает длину оставшейся байтовой строки (8 байт * 4 интервала). Второе значение, 3, является частью кодирования списков - оно указывает длину списка. Конечными значениями являются отдельные элементы списка.

Наконец, вам не нужен какой-либо случайный человек в Интернете, чтобы объяснить вам формат, вы можете просто прочитать формат из экземпляров в пакете binary (как только вы достаточно хорошо знакомы с Haskell).