Pravidla Ucet
Nepřihlášen

Článek

Menu

Práce s binárními soubory
Napsal: D-Sheep
Přidáno: 09.03. 2013

Ten nejúspornější a nejpokročilejší způsob, jak externě ukládat data ze hry.



Chtěl bych vám co nejpodrobněji popsat celou problematiku ukládání dat a nadhodit i pár užitečných vychytávek.

Binární soustava

Všechna data v počítači se uchovávají v tzv. binární nebo dvojkové soustavě. Jednotkou informace je "bit", který může nabývat hodnot 0 a 1, resp. nic a nějaká informace. Osm bitů vedle sebe tvoří bajt. Každý bit má potom o jeden řád větší význam (konkrétně v binární soustavě dvakrát větší). První je 1 nebo 0, druhý 2 nebo 0, třetí 4 nebo 0 atd. Každé číslo jde totiž zapsat jako součet mocnin dvou (1, 2, 4, 8, 16, 32, ...)

13 = 8 + 4 + 1 = 00001101
86 = 64 + 16 + 4 + 2 = 01010110
127 = 64 + 32 + 16 + 8 + 4 + 2 + 1 = 01111111

Protože jeden bajt je právě osm bitů, může nést pouze hodnoty od 0 do 255, tedy celkem 256 různých kombinací nul a jedniček.

Bitové operátory

V GML nás asi nejvíce budou zajímat pouze operátory << a >>. Tyto posouvají bity v čísle o několik řádů určeným směrem.

5 << 2 = 20
neboli
00000101 << 2 = 00010100

Externí soubory

Game Maker umí otevřít libovolný soubor z jakékoli složky v počítači. Při otevření je nutné někam uložit ID souboru, který se automaticky přiřadí, abychom mohli odkazovat pořád na ten samý soubor. Je totiž samozřejmost, že můžeme mít otevřených víc souborů najednou. Otevřeme tedy soubor:

f = file_bin_open("a.txt", 2);

//f je proměnná, která ukazuje na otevřený soubor
//a.txt je jméno souboru s příponou
//0 znamená čtení, 1 znamená zapisování, 2 obojí najednou

Bez jakéhokoliv přesnějšího určení GM otevírá tyto soubory ze stejné složky, kde je umístěn .gmk nebo .exe soubor hry. Jinou složku můžu pochopitelně určit vypsáním plné cesty k souboru (třeba "C:\GM\Moje_hra\a.txt"). Do binárních souborů jde zapisovat jen po bajtech. Může se vám zdát, že tím pádem jdou psát pouze čísla od 0 po 255, ale je tomu jinak. Díky systému ASCII, který určuje písmenům číselné kódy, jdou psát i texty. Příkaz je pro to následující:

file_bin_write_byte(f, <číslo>);

//f je identifikátor souboru (to co jsme nastavili při otevření)
//<číslo> je to, co chceme zapsat

Když tedy chci napsat do souboru číslo 100, nezobrazí se pak uvnitř "100", ale znak odpovídající hodnotě 100 v ASCII tabulce, což je "d". Úplně analogicky funguje i čtení ze souboru. Před jeho otevřením je potřeba nastavit čtení místo zapisování.

promenna = file_bin_read_byte(f);

Do proměnné se zase naopak dosadí číslo, které reprezentuje přečtený znak v souboru.


Hodnoty větší než 255

V případě moc vysokého čísla, kdy nám jeden bajt pro jeho vyjádření nestačí, trháme čísla do více bajtů. Každý další byte má pak 256× větší význam než ten předchozí. Číslo 880 se tedy rozdělí takto: 3 * 256 + 112. Do souboru pak chceme zapsat pouze čísla 3 a 112 s tím, že víme, že při zpětném čtení nesmíme zapomenout 3 znovu vynásobit 256.

a = 7560;
file_bin_write_byte(f, a div 256); //29
file_bin_write_byte(f, a mod 256); //136

//Zápis čísla 7560 na 16 bitů: 00011101 10001000

b = file_bin_read_byte(f) * 256 + file_bin_read_byte(f);

//Čtení stejného čísla

Také můžeme použít "profesionálnější" přístup. Všechny bity v čísle posuneme o 8 doprava, takže uřízneme ty menší. V podstatě to znamená to samé jako dělit/násobit 256, jen to počítač zpracovává jinak.

c = 9402; //00100100 10111010
file_bin_write_byte(f, c >> 8); //00100100, neboli prvních 8 bitů
file_bin_write_byte(f, c); //10111010 = posledních 8 bitů

d = (file_bin_read_byte(f) << 8) + file_bin_read_byte(f);

Největší číslo pro 16 bitů je 65 535 (2^16 - 1).

V tuto chvíli je nutné připomenout, že je důležité správně navrhnout strukturu souboru. Nesmíme ledabyle míchat zápisy na 1 a 2 bajty. Vždy musíme vědět, jak dané číslo přečíst zpět (na kolika je bajtech). Pro pořádek je tedy dobré držet se pouze jednoho stylu.

Zapisování textu

Texty nebo stringy jsou doslova přeloženo řetězce znaků. Můžeme je také vidět jako několik po sobě jdoucích kódů ASCII. Proto se jejich převod na bajty dělá písmeno po písmeni. Zde je mnou vyrobený skript pro zápis stringů:

//file_bin_write_string(fileid, string);
var i, l;
l = string_length(argument1);
file_bin_write_byte(argument0, l);
for (i = 1; i <= l; i += 1)
  file_bin_write_byte(argument0, ord(string_char_at(argument1, i)));

Skript nejdříve zapíše délku stringu (max. 255 znaků) a potom samotný string. Skript pro čtení je hodně podobný:

//file_bin_read_string(fileid);
var l, s;
l = file_bin_read_byte(argument0);
s = "";
repeat (l)
  s += chr(file_bin_read_byte(argument0));
return s;

Princip čtení je jednoduchý: nejdřív zjistím kolik toho mám přečíst a potom si to přečtu. Tím se šetří místem narozdíl od stringů s fixní délkou. Žádný bajtík není zbytečný. Výsledný soubor vygenerovaný level editorem pro skákačku může vypadat třeba takto.


Po ukončení práce s otevřeným souborem je dobré ho také zavřít, aby se zbytečně nepletl v paměti.

file_bin_close(f);

Mezi další užitečné příkazy patří:
• file_bin_rewrite(fileid), který smaže obsah souboru pro kompletní přepsání
• file_bin_seek(fileid, position) - přesune pozici čtení/zápisu na určitou pozici v souboru, kde position rovno 0 je přesun na začátek
• file_bin_position(fileid) - získání aktuální pozice čtení/zápisu
• file_bin_size(fileid) - vrátí velikost souboru, to znamená počet zapsaných bajtů.

Pár tipů na závěr

Obecně platí, že pokud otevíráte soubor, který neexistuje, vytvoří se nový s tímto jménem a umístěním.
Narozdíl od textových souborů mohou mít ty binární libovolnou příponu.

Klíčová slova: binární externí soubory file bin ukládání dvojková soustava D-Sheep
 

Komentáře:

Velkej Chytrák
Copyright (c) 2001-2010