[ mr.marvin @ 23.06.2007. 22:33 ] @
Ako imam fajl koga otvaram binarno, svaki ucitani podatak za Python je string, koji je zapravo ASCII, int ili hex. Sad, ima li kakav efikasan nacin da se konverzija uradi tako da dobijem str/int/hex (onako kako je u fajlu) ili moram za svaki file("file.bin").read(1) da provjeram da li je konverzija moguca?

Trazio sam na netu, ali se nisam snasao.
[ jablan @ 23.06.2007. 22:50 ] @
Ja ne razumem o kakvoj konverziji pričaš. Šta podrazumevaš pod str/int/hex?

[Ovu poruku je menjao jablan dana 24.06.2007. u 00:06 GMT+1]
[ mr.marvin @ 23.06.2007. 23:45 ] @

f = file("somefile.bin", "rb")
c = f.read(1)
print c

Sad, c moze biti ASCII, moze int ili hex, ali je uvijek string, tako ga Python "cita". Ako ja znam da je cijeli broj onda ga pretvaram sa int(broj, osnova) itd. Ima li nacina da Python sam "ukapira" da je nesto ASCII, int ili vec koji tip?
[ jablan @ 23.06.2007. 23:50 ] @
Nema šta Pajton da kapira, c je uvek string. Hoćeš li malo pojasniti šta misliš kad kažeš ASCII, hex i int? Svaki karakter može se zapisati kao neki ascii simbol, heksadecimalni ili decimalni broj. Ali to je samo interpretacija, odnosno njegov zapis. U memoriji je on uvek jedan karakter, odnosno bajt (da ne komplikujemo sad širenjem priče na Unikod).

Na primer:
Code:

jablan@jablan-laptop:~$ python
Python 2.5.1 (r251:54863, May  2 2007, 16:56:35) 
[GCC 4.1.2 (Ubuntu 4.1.2-0ubuntu4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> c = 'a'
>>> '%s' % c
'a'
>>> '%d' % ord(c)
'97'
>>> '%x' % ord(c)
'61'


Kapiš?
[ mr.marvin @ 24.06.2007. 00:31 ] @
Kapisko.

Kako da...

Code:

>>> a.get(12)
'\x00\x00\x00\x00\x04\x00\x00\x00\x14\x00\x00\x00'


...pretvorim u int? Odnosno, jednu po jednu stavku...
[ jablan @ 24.06.2007. 00:37 ] @
Code:

>>> s = '\x00\x00\x00\x00\x04\x00\x00\x00\x14\x00\x00\x00'
>>> i = [ord(c) for c in s]
>>> i
[0, 0, 0, 0, 4, 0, 0, 0, 20, 0, 0, 0]

ili, još kraće,
Code:

>>> map(ord, s)
[0, 0, 0, 0, 4, 0, 0, 0, 20, 0, 0, 0]

Samo što čujem da će filter i map funkcije da izbace u P3000.
[ Au197/79 @ 24.06.2007. 10:51 ] @
Ja sam čuo da će samo reduce da izbace
[ mr.marvin @ 24.06.2007. 11:17 ] @
Hvala na odgovorima, to je ono sto mi je trebalo. Jos me nesto buni.

Code:

>>> int('/x14', 16)

Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    int('/x14', 16)
ValueError: invalid literal for int() with base 16: '/x14'
>>> int('x14', 16)

Traceback (most recent call last):
  File "<pyshell#8>", line 1, in <module>
    int('x14', 16)
ValueError: invalid literal for int() with base 16: 'x14'
>>> int('0x14', 16)
20


Kako se mice ovaj "/" znak; i zasto Python izostavlja nulu kad citam podatke iz fajla?
[ jablan @ 24.06.2007. 22:20 ] @
Ja ne mogu, aj neko drugi...
[ alex @ 26.06.2007. 12:55 ] @
Ako bi mogao, posalji deo svog kôda, kako bi mogli da sagledamo ceo problem. Mozes li da posaljes deo koda gde citas informacije iz fajla i primer fajla?
Pre svega, ne verujem da ti python vraca /x14 (sigurno je u pitanju \x14).

Inace, ako hoces da sklonis prva dva znaka iz stringa, najlakse je sa '/x14'[2:]', mada uveren sam da cemo naci bolje resenje kad vidimo kôd.
[ mr.marvin @ 28.06.2007. 14:53 ] @
Alex, da, u pitanju je \x14; uporno mrkam / i \ na svakom mogucem koraku.

Radi se o tome da pisem loader za *.psy fajlove (Psycle tracker), i kako niakd nisam radio tako nesto naisao sam na velike probleme usljed nepoznavanja nekih osnovnih stvari. Probacu da ovaj pšost ne buide suvise dug...

Opis formata nalaz se na ovoj adresi i nakon preegledanja poceo sam da shvatam kako to funkcionise. Prvo sam otvorio fajl u SciTe da vidim kako to otprilike izgeda i zatim sam poceo da pisem kod. Pristup sa f.read() (otvoreno sa "rb") dio po dio, vec kako zahtjeva file-format dokument.

Ali, ubzo mi se nametnulo mnogo pitanja...

Zasto je oupste potenbno navoditi sizeof(int) i kako to radi u Pythonu? Nasao: import ctype. Ali sta je sa sizeof(bool), njega nema u listi ctypes?

Zatim nikako da ukpocam kako se jedan int niz upisuje/cita binarno? Goglanjem sam nasao nesto o riff formatu, a u tom kontekstu i modul struct.

Elem, zakljuciuo sam da je nepotrebno i veoma neefikasno pisati ovakav izmisljanjem tople vode (mozda je bolje radi ucenja programiranja?) vec je efikasnije koristiti struct.

Glavno pitanje koje me sad okupira jeste kako formatirati struct.pack(). Ako imam 8 karaktera koji se zavresavaju sa 2 null, ili niz int brojeva + 3NULL, kako to formatirati u struct.unpack(fmt,s)?


Linkovi

Psycle file format
http://svn.sourceforge.net/vie...?revision=4993&view=markup

Primjeri psy fajlova
http://psycle.pastnotecut.org/...ate&how=DESC&styleid=1

Struct
http://www.python.org/doc/1.5.2p1/lib/module-struct.html

Ctype
http://docs.python.org/lib/node454.html

PS
Zna li ko za relativno razumljiv tekst koji na jednom mjestu objasnjava silne tipove nabrojane u tabeli u ctype dokumentu?
[ mr.marvin @ 03.07.2007. 22:35 ] @
Evo da odgovorim ja i napisem sta sam naucio :) , zbog drugih koje bi ovo interesovalo. Ako progresim gdje u terminologiji, ispravite me.

Kada se fajl otvori za binaran pristup u Pythonu, to se radi ovako:

psy = open("psyfile.psy", 'rb')

Jedan bajt se dobije na jednostavan nacin:

byte = psy.read(1)

Medjutim, da li je taj jedan bajt i citav "broj", zavisi od tipa trazenog podatka. Ono sto ja nisam znao jeste koliko odredjeni tip podataka zauzima prostora u memoriji:

Code:

>>> from ctypes import *
>>> sizeof(c_int)
4
>>> sizeof(c_uint)
4
>>> sizeof(c_ushort)
2


U specifikaciji za vrstu fajla koju citam, jasno se navodi koja vrijednost se cita kojim redom. Tako, ako treba da ucitam vrijdnost za oznaku verzije, koje je tipa int, treba da ucitam 4 bajta (duzina c_int je 4, kao sto je navedeno gore) i da ih pretvorim u... pa recimo... koristan oblik. Npr:

Code:

a = '\x01\x01\x01\x01'


...nije cetiri jedinice, vec:

Code:

>>> struct.unpack("i", a)
(16843009,)


Modul struct zaduzen je za ovu konverziju; citanjem dokumentacije za ovaj modul, kao i ctypes lako se dodje do rjesenje i odgovora koliko se cega cita za odredjeni tip podataka (sizeof(tip_podatka)), a zatim i kako se ti podaci konvertuju (struct.unpack(formatiranje, string)).

To je sva filozofija, a gomila zbunjujucih pitanja u prethodnom postu nastalaje iz nepoznavanja primitivnih c tipova podataka. Srecom, sve je uredno navedeno u Python helpu.
[ alex @ 04.07.2007. 10:29 ] @
Svaka cast. Hteo sam da ti napisem da procitas Python uputstvo, ali je mnogo lepse kad sam to otkrijes. Python uputstvo je odlicno stivo.