Základy binární serializace

RunUO Toto je první díl meho článku, kde se chci zabývat základním principem pro binární zápis objektů do souboru. Tuto metodu využívá emulátor RunUO (ta bude podrobnějí rozebrána v druhém dílu), ale je využitelný praktický kdekoliv a je mnohem efektivnější než plain text (v čisté textové formě) ukládání.

Pokud jste znalí emulátoru Sphere, připadně ji máte dokonce spuštěnou na vašem počítači, zajistě jste zkoumali, jak vypadá tzv. Save světa. Je to obyčejný textový formát, který je čitelný v libovolném textovém editoru. Ti bystřejší v něm poznávají formát klasických INI souborů. Není zde žádný pokus o komprimaci dat, proto jsou tyto soubory velice objemné u zaběhnutých shardů.

Když se podíváte v textovém editoru na "Save" u RunUO (např. Saves/Mobiles/Mobiles.bin), uvídíte převážně bíla místa proložená nějakými znaky. Nyní se na ten samý soubor podívejte přes nějaky HEX editor (např. PSPad). Nebudu zde vysvětlovat HEXa editaci, podstatné je, že tato bíla místa ve skutečnosti něco obsahují, pouze textové editory pro to nemají grafickou reprezentaci (resp. není obsažena ve většině fontů či znakových sad). Datová velikost takového místa je zpravidla 1 Byte, ovšem existují znakové sady, které kvůli své robustnosti potřebují 2 Byte pro jeden znak.

Textový editor zpravidla čte soubor po Bytech, získánou hodnotu nahradí podle tabulky znakové sady odpovídajícím znakem. Jelikož je 1 Byte kombinací 8 bitů (nejmenší počítačová jednotka), vzniká tak možnost do něj zapsat až 256 hodnot, tedy číslo od 0 do 255. Pokud spojíme 2 Byte, můžeme jejich kombinací získat číslo od 0 do 65535, pro 3 Byte je to již číslo kolem 1,6 milionů, a tak dále.

Nyní se tedy dostáváme k základní myšlence binární serializace. Definujme si různé datové typy, které mají pevně stanovenou datovou velikost v Bytech. Výstupem těchto typů je vždy číslo, které se zapíše binárně na určitou pozici a vždy zabere určený počet Byte. Za tohoto předpokladu, jsem opět schopni toto číslo přečíst, pokud víme, kolik zabírá Byte.

Dalším podstatným krokem je zajistit, aby mechanismus, který tyto data zapsal byl prakticky totožný s mechanismem, který je bude číst. Jinými slovy, tyto mechanismy musí mít naprosto stejný postup procházení daným souborem, s tím rozdílem, že jeden zapisuje a druhy čte.

Na závěr malý příklad. Dejme tomu, že si chceme do souboru zaznamenat dvě velká čísla, např 5698156621 a 1843218632. Můžeme je zapsat čistě textově, ale zabere to více datového prostoru, i když v tomhle případě je to mizivý rozdíl. Celková velikost souboru bude 20 Bytes (pro každou číslici 1 Byte).

Pokud chceme daná čísla zapsat binárně, nejsnazší způsob je pomocí kalkukačky převést do HEXa podoby. Vyjdou nam hodnoty 153A2F84D pro první a 6DDD48C8 pro druhý. Tento tvar je již jistý druh komprimace, neboť do jednoho Byte se vejde hexa číslo 00 až FF. Musíme si dát pozor, neboť první tvar má lichý počet znaků, takže je nutno na začátek doplnit 0, aby to vyšlo. Po přepisu si zobrazíme soubor klasicky textově a bude tam toto "S˘řMmÝHČ". Tímto zápisem jsme ušetřili 11 Byte.

Všimněte si, že první číslo zabírá 5 Byte, kdežto druhé jen 4. Takže pokud budete chtít obě čísla přečíst, musíte programu řící, aby nejprve načetl 5 Byte a pak aby přečetl 4 Byte. Můžete samozřejmě při zápisu prodloužit druhé číslo o 1 Byte, když na začátek hexa tvaru dopíšete 00. Pak nemusíte v programu dělat speciální postup čtení, ale budete vždy číst 5 Byte.

Tak to bude pro dnešek vše. Uvítám jakékoliv připomínky a komentáře. Nemám patent na rozum, takže nemusí být vše uplně přesné.

Poslal: Fredy - Úterý, 18 leden, 2005 - 23:03 CET