Funkce pro zápis do binárních souborů

Sem vkládejte editovatelné kusy kódu a tutoriály.
Odpovědět
Uživatelský avatar
DDL Blue
Živý stín
Příspěvky: 431
Registrován: srpen 6, 2011, 7:21 pm

Funkce pro zápis do binárních souborů

Příspěvek od DDL Blue » únor 1, 2014, 2:35 am

dbBin
Ahoj!

V rámci mého aktuálního projektu jsem zabrousil do práce s binárními soubory. Protože GM umí zapisovat pouze byty (8bitů, tj.čísla 0-255) a nic jinýho, rozhodl jsem se, že si napíšu funkce, které umí zapisovat čísla libovolného rozsahu, a texty (řetězce, tj. stringy).

Jsou to funkce:
dbBin_write(file,type,value); //pro zápis
dbBin_read(file,type); //pro čtení

argumenty:
file...Odkaz na otevřený binární soubor (to, co vrací file_bin_open(...))

type...Typ hodnoty. Udává se číslem. 0 pro řetězec, 1 a více pro čísla. Udává velikost hodnoty v bytech. Ovlivníte tím tedy to, jak moc velká čísla můžete zapsat a kolik místa to v souboru zabere. Nejvyšší možné číslo je vždy 256^type. Takže pokud je zapsané číslo v rozsahu 0-255, lze použít typ 1, pokud v rozsahu 0-65 536, stačí typ 2 atd. Desetinná, ani záporná čísla zapisovat neumí, to si už budete muset dopsat sami ;).

value...Hodnota, kterou chcete uložit. V závislosti na typu text, nebo číslo.

Kód:
Spoiler: ukázat
dbBin_write(file,type,value);

Kód: Vybrat vše

///dbBin_write(file,type,vaule);
//wtf
if real(argument1)<0 {return -1;}
//string
if real(argument1)==0{
    var dbBinStr, dbBinStrl, dbBinStringBreaker;
    dbBinStringBreaker=3; //ASCII hodnota znaku pro ukončení stringu    
    dbBinStr=string(argument2);
    dbBinStrl=string_length(string(argument2));    
    for (i=0; i<dbBinStrl; i+=1){
        file_bin_write_byte(argument0,ord(string_char_at(dbBinStr,i+1)));    
        }
    file_bin_write_byte(argument0,dbBinStringBreaker);
    return 1;
}
//real
if real(argument1)>0{
    for(i=0; i<argument1; i+=1){
        file_bin_write_byte(argument0,floor(real(argument2)/(power(256,real(argument1)-(i+1)))));
        }
    }    
return -1;
//by DDL Blue 2014
dbBin_read(file,type);

Kód: Vybrat vše

///dbBin_read(file,type);
//wtf
if real(argument1)<0 {return -1;}
//string
if real(argument1)=0{
    var dbBinStr, dbBinStringBreaker, dbBinByte;
    dbBinStr="";
    dbBinByte=0;
    dbBinStringBreaker=3; //ASCII hodnota znaku pro ukončení stringu
    while(file_bin_position(argument0)<=file_bin_size(argument0)){
        dbBinByte=file_bin_read_byte(argument0);
        if dbBinByte==dbBinStringBreaker{
            break;
            }else{
            dbBinStr+=chr(dbBinByte);
            }   
        }
    return dbBinStr;
    }
//real
if real(argument1)>0{
    var dbBinVal;
    dbBinVal=0;
    //var dbBinVal;
    for(i=0; i<real(argument1); i+=1){
        dbBinVal+=file_bin_read_byte(argument0)*power(256,real(argument1)-(i+1));
        }
    return dbBinVal;
    }    
return -1;
//by DDL Blue 2014
Příklad:
Spoiler: ukázat
Create:

Kód: Vybrat vše

//zápis do souboru
f=file_bin_open("test.bin",1);
dbBin_write(f,0,"Ahoj!");
dbBin_write(f,1,5);
dbBin_write(f,2,300);
dbBin_write(f,4,123456789); //číslo s velkým rozsahem
dbBin_write(f,1,256); //přesáhne limit 255, vátí se zpět na nulu.
dbBin_write(f,1,260); //přesáhne limit 255, uloží se 260-256=4
dbBin_write(f,2,2452); //zvolen jiný* datový typ, než při čtení -> špatně přečtená hodnota
dbBin_write(f,0,"Pokud se jednou spletete, všechny další čtení souboru dopadnou špatně.");
file_bin_close(f);

////////////////////////////////////////////////////


//následné přečtení
f=file_bin_open("test.bin",0);
show_message(string(dbBin_read(f,0)));
show_message(string(dbBin_read(f,1)));
show_message(string(dbBin_read(f,2)));
show_message(string(dbBin_read(f,4)));
show_message(string(dbBin_read(f,1)));
show_message(string(dbBin_read(f,1)));
show_message(string(dbBin_read(f,1))); //* 1 místo 2
show_message(string(dbBin_read(f,0))); //Na začátku bude znak, který tam nemá co dělat. To samé by se stalo při načítání čísla,
                                       //načetla by se vždy chybná hodnota. 
file_bin_close(f);
V obouch funkcích je proměnná dbBinStringBreaker. Její výchozí hodnota je 3, ale může být libovolná. Určuje ascii hodnotu znaku, který ukončuje řetězce. V obouch funkcích musí být pochopitelně nastavená na stejnou hodnotu. Také by neměla mít hodnotu, která je vyhrazená pro nějaký znak, který budete chtít v textu zapsat.

Je nutné číst hodnoty se stejným číslem typu, v jakém byly zapsány. Pokud se jednou spletete, všechny další hodnoty, které přečtete, se přečtou špatně!

[/size]

GM:S jsem nezkoušel, ale nevidím důvod, proč by to nemělo fungovat i tam. Doufám, že se to někomu bude hodit ;). Otázky, nápady, popř. výtky sem.
Zkoukněte moji hudební galerii ;). Nebo vyzkoušej můj generátor akordů!
Řikejte mi prostě Blue...

Uživatelský avatar
D-Sheep
Příspěvky: 768
Registrován: září 7, 2011, 10:17 pm
Facebook: http://facebook.com/sheepdave
Bydliště: Praha, CZE
Kontaktovat uživatele:

Re: Funkce pro zápis do binárních souborů

Příspěvek od D-Sheep » únor 1, 2014, 12:27 pm

Celkem šikovný věcičky, ale daly by se zrychlit. Místo násobení 256 a používání spoustu funkcí okolo by stačil bitový posun (>>), který GM jakž takž zvládá.

Čtení stringů by taky šlo (sice skoro minimálně) zrychlit, protože máš na konci vždy garantovaný ukončující znak (který je mimochodem často binární nula, ne trojka, ale máš pravdu, že je fuk, čím to ukončíš...).
Proto může být cyklus jen while (true).

Předané argumenty snad nemusí být ve funkci real... Lidi jsou sice hloupý, ale snad ví, že mají psát 0 a ne "0".

Proč vracíš při psaní čísla -1? Sice se asi málokdy stane, že se zápis nepovede, ale tohle není programátorsky správně.

Hlavičku skriptů jsi očividně zkopíroval, u obou máš write :P

Uživatelský avatar
DDL Blue
Živý stín
Příspěvky: 431
Registrován: srpen 6, 2011, 7:21 pm

Re: Funkce pro zápis do binárních souborů

Příspěvek od DDL Blue » únor 14, 2014, 12:15 pm

D-Sheep píše:Celkem šikovný věcičky, ale daly by se zrychlit. Místo násobení 256 a používání spoustu funkcí okolo by stačil bitový posun (>>), který GM jakž takž zvládá.
Na tuhle funkci jsem si vůbec nevzpoměl. :confu: Ale tak přepisovat to už asi nebudu. Nejsem si jistej, jestli to má v GM vůbec smysl :).
Čtení stringů by taky šlo (sice skoro minimálně) zrychlit, protože máš na konci vždy garantovaný ukončující znak (který je mimochodem často binární nula, ne trojka, ale máš pravdu, že je fuk, čím to ukončíš...).
Proto může být cyklus jen while (true).
To mi přišlo nebezpečný. V souboru může bejt nějakej fail, kterej by mohl skončit nekonečným cyklem. Toho sem se chtěl vyvarovat. Původně sem tam měl tu nulu, ale na wiki byla nula napsaná jako "binární nula" a u trojky bylo "end of text", tak sem tam dal tu trojku. Tím se ale vracíme k tomu, že je to fakt jedno. :)
Předané argumenty snad nemusí být ve funkci real... Lidi jsou sice hloupý, ale snad ví, že mají psát 0 a ne "0".
Jo, tohle sem tam přidal jen kvůli tomu,, že sem to dával sem. Chtěl sem to udělat co nejvíc blbuvzdorný...
Proč vracíš při psaní čísla -1? Sice se asi málokdy stane, že se zápis nepovede, ale tohle není programátorsky správně.
Co přesně se ti na tom nelíbí? Koukal sem, že to možná v nějakým momentě nemusí vrátit nic, což by byl fail. Ještě na to kouknu. Ale jinak vracet -1 při neúspěchu mi příde v pohodě.
Hlavičku skriptů jsi očividně zkopíroval, u obou máš write :P
Damn, myslel sem, že sem tohle opravoval :| :).
Zkoukněte moji hudební galerii ;). Nebo vyzkoušej můj generátor akordů!
Řikejte mi prostě Blue...

Odpovědět

Kdo je online

Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 2 hosti