OVH Cloud OVH Cloud

lecture d'entier dans un fichier.data

4 réponses
Avatar
Sébastien Kirche
Bonjour,

je me suis fait un petit utilitaire qui va chercher dans une ressource (au
sens macintosh) certaines informations.

Mon problème est que je cherche une chaîne dont la position de début est
connue, mais pas la longueur qui est elle codée aussi dans la ressource.
Et je n'arrive pas à convertir en entier

ressource.data[offset longeurNom: offsetlongueurNom +1]

qui est apparemment un tableau d'entiers pour ensuite récupérer

ressource.data[offset nom:offset nom+longueur nom]

int() ou long() protestent sur la nature de la chaîne que je leur passe.

Je m'en suis quand même tiré mais cela ne me semble pas terrible : avec 2
routines empruntées je fais en 2 temps tableau de bytes -> tableau de
bits -> entier.

Voici un extrait de mon code et les 2 fonctions de conversion,
connaissez-vous un moyen plus simple ? Merci.

8<------8<------8<------8<------8<------8<------8<------8<------8<------
# Fonctions bytes2bin et bin2dec (c) Travis Shirk <travis@pobox.com>
# empruntées du projet eyeD3 http://eyed3.nicfit.net/

# Accepts a string of bytes (chars) and returns an array of bits
# representing the bytes in big endian byte (Most significant byte/bit first)
# order. Each byte can have it's higher bits ignored by passing an sz arg.
def bytes2bin(bytes, sz = 8):
if sz < 1 or sz > 8:
raise ValueError("Invalid sz value: " + str(sz));

retVal = [];
for b in bytes:
bits = [];
b = ord(b);
while b > 0:
bits.append(b & 1);
b >>= 1;

if len(bits) < sz:
bits.extend([0] * (sz - len(bits)));
elif len(bits) > sz:
bits = bits[:sz];

# Big endian byte order.
bits.reverse();
retVal.extend(bits);

if len(retVal) == 0:
retVal = [0];
return retVal;

# Convert and array of "bits" (MSB first) to it's decimal value.
def bin2dec(x):
bits = [];
bits.extend(x);
bits.reverse();

multi = 1;
value = long(0);
for b in bits:
value += b * multi;
multi *= 2;
return value;
8<------8<------8<------8<------8<------8<------8<------8<------8<------
import macostools
from Carbon import Res

rf = Res.FSpOpenResFile(aliasFile, 0)
alis = Res.GetResource('alis', 0)

volNameLen = bin2dec(bytes2bin(alis.data[10:11]))
#volName = repr(alis.data[11:11+volNameLen])#retourne une chaîne quotée
volName = alis.data[11:11+volNameLen]
Res.CloseResFile(rf)
8<------8<------8<------8<------8<------8<------8<------8<------8<------


--
Sébastien Kirche

4 réponses

Avatar
F. Petitjean
Bonjour,


ressource.data[offset nom:offset nom+longueur nom]

int() ou long() protestent sur la nature de la chaîne que je leur passe.

Je m'en suis quand même tiré mais cela ne me semble pas terrible : avec 2
routines empruntées je fais en 2 temps tableau de bytes -> tableau de
bits -> entier.

Voici un extrait de mon code et les 2 fonctions de conversion,
connaissez-vous un moyen plus simple ? Merci.

8<------8<------8<------8<------8<------8<------8<------8<------8<------
# Fonctions bytes2bin et bin2dec (c) Travis Shirk
# empruntées du projet eyeD3 http://eyed3.nicfit.net/

# Accepts a string of bytes (chars) and returns an array of bits
# representing the bytes in big endian byte (Most significant byte/bit first)
# order. Each byte can have it's higher bits ignored by passing an sz arg.
def bytes2bin(bytes, sz = 8):
if sz < 1 or sz > 8:
raise ValueError("Invalid sz value: " + str(sz));

retVal = [];
for b in bytes:
bits = [];
b = ord(b);
while b > 0:
bits.append(b & 1);
b >>= 1;

if len(bits) < sz:
bits.extend([0] * (sz - len(bits)));
elif len(bits) > sz:
bits = bits[:sz];

# Big endian byte order.
bits.reverse();
retVal.extend(bits);

if len(retVal) == 0:
retVal = [0];
return retVal;
Humm tous ces points virgules inutiles, ils étaient d'origine et celà

ne vous a pas mis la puce à l'oreille ? (encore une copie servile d'un
algorithme écrit dans un autre langage ?). L'adage « copier est un
vilain défaut » semble s'appliquer ici.

# Convert and array of "bits" (MSB first) to it's decimal value.
def bin2dec(x):
bits = [];
bits.extend(x);
bits.reverse();

multi = 1;
value = long(0);
for b in bits:
value += b * multi;
multi *= 2;
return value;
8<------8<------8<------8<------8<------8<------8<------8<------8<------
import macostools
from Carbon import Res

rf = Res.FSpOpenResFile(aliasFile, 0)
alis = Res.GetResource('alis', 0)

volNameLen = bin2dec(bytes2bin(alis.data[10:11]))
Il me semble que dans votre cas len(data) > 11 et donc alis.data[10:11]

c'est tout simplement alis.data[10]. Autrement dit : on combine des
manipulations de bits en pseudo-python tout ça pour avoir la valeur
entière associée à un pauvre octet !
#volName = repr(alis.data[11:11+volNameLen])#retourne une chaîne quotée
volName = alis.data[11:11+volNameLen]
Res.CloseResFile(rf)
8<------8<------8<------8<------8<------8<------8<------8<------8<------

J'essaierais d'abord ord(byte) et si cela ne covient pas quelque chose

comme
import struct
struct.unpack('>B', byte)[0]

voili voilà

Avatar
Sébastien Kirche
Le 11 fév 2005, F. Petitjean a formulé :

[snip le code pompé]

Humm tous ces points virgules inutiles, ils étaient d'origine et celà
ne vous a pas mis la puce à l'oreille ? (encore une copie servile d'un
algorithme écrit dans un autre langage ?). L'adage « copier est un
vilain défaut » semble s'appliquer ici.


En fait je ne me suis pas posé trop de questions en effet. Je n'ai pas
cherché à réécrire ce code. J'en suis à mes débuts en python et certaines
choses évidentes ne me sautent encore pas aux yeux :)

volNameLen = bin2dec(bytes2bin(alis.data[10:11]))
Il me semble que dans votre cas len(data) > 11 et donc alis.data[10:11]

c'est tout simplement alis.data[10]. Autrement dit : on combine des
manipulations de bits en pseudo-python tout ça pour avoir la valeur
entière associée à un pauvre octet !


Encore raison : dans ce cas précis, la longueur des données à lire est codée
dans un seul octet.

J'essaierais d'abord ord(byte) et si cela ne covient pas quelque chose
comme
import struct
struct.unpack('>B', byte)[0]


Excellent. La lib struct fournit exactement ce dont j'ai besoin pour relire
des structures C. Et remplace avantageusement le code que j'ai
maladroitement récupéré (et encore vous n'avez pas tout vu !)

Je viens de vérifier mais elle ne figure pas dans mon Python Quick
Reference : une nouveauté 2.4 ?
Je n'ai pas assez cherché dans la Library Reference.

voili voilà


Merci beaucoup !

--
Sébastien Kirche


Avatar
loic.mahe
Bonjour,

pour convertir une string normale en hexadécimal je ferais:

'string'.encode('hex_codec')

pour convertir une string hexa en int je ferais:

int ('string hexa', 16)

donc en une seule ligne:

int ( 'string'.encode('hex_codec') , 16 )

et voilà ...
si ca ne marche pas donne nous un exemple de string que tu veux convertir ...

A+

Loïc
Avatar
Sébastien Kirche
Le 17 Feb 2005, Lo a formulé :

Bonjour,


Bonjour,

pour convertir une string normale en hexadécimal je ferais:

'string'.encode('hex_codec')


Intéressant.

pour convertir une string hexa en int je ferais:

int ('string hexa', 16)


Oui, ça j'ai vu depuis.

donc en une seule ligne:

int ( 'string'.encode('hex_codec') , 16 )

et voilà ... si ca ne marche pas donne nous un exemple de string que tu
veux convertir ...


Struct convient tout à fait à mes besoins (relire des structures C sauvées
dans un fichier ressource mac).

Le problème c'est que je débute et que je ne connais pas toutes les
possibilités du langage et des librairies standard. Mais j'avance :)

--
Sébastien Kirche