Récupérer les octets d'un fichier de gauche à droite

Informations pour bien débuter en PureBasic
Avatar de l’utilisateur
microdevweb
Messages : 1800
Inscription : mer. 29/juin/2011 14:11
Localisation : Belgique

Récupérer les octets d'un fichier de gauche à droite

Message par microdevweb »

Bonjour à tous,

Dans certain cas il est nécessaire de pouvoir lire dans un fichier un certain nombre d'octets de gauche à droite.

Exemple avec un fichier MIDI.

L'entête du fichier est la suivante "4D546864" ou "MThd" en caractères, si par exemple vous utilisé

Code : Tout sélectionner

Hex(ReadLong(0)) ; donne 6468544D
Vous constaterez que le résultat est inversé.

Voici une exemple avec une procédure qui vous donnera le résultat attendu.

Code : Tout sélectionner

; Create file for testing
CreateFile(0,"Test.txt")
; write some values for testing
WriteByte(0,$4D)
WriteByte(0,$54)
WriteByte(0,$68)
WriteByte(0,$64)
CloseFile(0)
OpenFile(0,"Test.txt")
; I read a long (4 octeds), look the result
; The result is wrong it is inverted.
Debug "The result is wrong it is inverted."
Debug Hex(ReadLong(0))
CloseFile(0) 
Procedure ReadOcteds(IdFile,NumberOcteds,*Variable)
  Protected v.l,i,p=NumberOcteds
  For i=1 To NumberOcteds
    p-1
    v=ReadByte(IdFile)
    MoveMemory(@v,*Variable+p,1)
  Next
EndProcedure

Define test.l
OpenFile(0,"Test.txt")
ReadOcteds(0,4,@test)
CloseFile(0) 
Debug "The result is correct."
Debug Hex(test)

Dernière modification par microdevweb le dim. 06/août/2017 9:08, modifié 2 fois.
Windows 10 64 bits PB: 5.70 ; 5.72 LST
Work at Centre Spatial de Liège
Avatar de l’utilisateur
Ar-S
Messages : 9476
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: Récupérer les octets d'un fichier de gauche à droite

Message par Ar-S »

Sympa ça.
N'oubliez pas de rajouter un dernier CloseFile(0) en fin de code.
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Avatar de l’utilisateur
JohnJohnsonSHERMAN
Messages : 648
Inscription : dim. 13/déc./2015 11:05
Localisation : Allez, cherche...
Contact :

Re: Récupérer les octets d'un fichier de gauche à droite

Message par JohnJohnsonSHERMAN »

Effectivement on a parfois ce problème, qui vient de l'ordre d'écriture des octets, ce qu'on apelle l' endianness. Typiquement, on utilise sur les architectures Intel-PC la méthode dite "little-endian", ou octet de poids faible en tête, et sur d'autres archi moins répandues (ARM, Sparc,...), la méthode du "big-endian", octet de poids fort en tête.
En big-endian, le premier bit est le plus élevé (celui qui code la partie la plus grande), et le dernier le plus faible, et inversement en little-endian, le premier est le plus faible...

Ainsi si l'on écrit le nombre 01A4 (420) en little-endian (comme c'est le cas sur la plupart de nos PC), puis que l'on lit l'un aprés l'autre ses deux octets, on a A401. En mémoire, les octets sont dans le sens inverse de celui dans lequel on les écrirait naturellement.

Je viens justement d'avoir ce probléme avec des cartes altimétriques de la Nasa qui sont en big-endian :)

Merci de ta procédure :) Elle va me servir
"Le bug se situe entre la chaise et le clavier"
Votre expert national en bogage et segfaults.

CPU : AMD A8 Quad core - RAM 8Gb - HDD 2To
  • Windows 10 x64 - PB 5.61 x64
  • Linux Ubuntu 16.04 LTS x64 (dual boot) - PB pas encore réinstallé
Avatar de l’utilisateur
microdevweb
Messages : 1800
Inscription : mer. 29/juin/2011 14:11
Localisation : Belgique

Re: Récupérer les octets d'un fichier de gauche à droite

Message par microdevweb »

Bien vu Ar-S,

J'ai corrigé.
Windows 10 64 bits PB: 5.70 ; 5.72 LST
Work at Centre Spatial de Liège
Avatar de l’utilisateur
Zorro
Messages : 2185
Inscription : mar. 31/mai/2016 9:06

Re: Récupérer les octets d'un fichier de gauche à droite

Message par Zorro »

ces procedures font la meme chose :)

Code : Tout sélectionner


Procedure.w xchEndianW(e.w)
		;by wilbert
		ProcedureReturn (e & $FF) << 8 + (e >> 8) & $FF
EndProcedure

Procedure xchEndianL(e.l)
		; by wilbert
		ProcedureReturn (e & $FF) << 24 + (e & $FF00) << 8 + (e >> 8) & $FF00 + (e >> 24) & $FF
EndProcedure
Image
Image
Site: http://michel.dobro.free.fr/
Devise :"dis moi ce dont tu as besoin, je t'expliquerai comment t'en passer"
G-Rom
Messages : 3627
Inscription : dim. 10/janv./2010 5:29

Re: Récupérer les octets d'un fichier de gauche à droite

Message par G-Rom »

Zorro a écrit :ces procedures font la meme chose :)

Code : Tout sélectionner

Procedure.w xchEndianW(e.w)
      ;by wilbert
      ProcedureReturn (e & $FF) << 8 + (e >> 8) & $FF
EndProcedure

Procedure xchEndianL(e.l)
      ; by wilbert
      ProcedureReturn (e & $FF) << 24 + (e & $FF00) << 8 + (e >> 8) & $FF00 + (e >> 24)    & $FF
EndProcedure

Debug htonl_(65)
Debug xchEndianL(65)
    
Debug htons_(65)
Debug xchEndianW(65)


Les API aussi le font très bien , portable en plus :

https://linux.die.net/man/3/htonl
https://msdn.microsoft.com/fr-fr/librar ... s.85).aspx
PAPIPP
Messages : 534
Inscription : sam. 23/févr./2008 17:58

Re: Récupérer les octets d'un fichier de gauche à droite

Message par PAPIPP »

Bonjour à tous

Little-endian a encore frappé.

En effet seules, les architectures Motorola 68000, les SPARC (Sun Microsystems) ou encore les System/370 (IBM). Ou le protocole TCP/IP, sont en big-endian ou gros-boutistes ou mot de poids fort en tête.

Mais Intel a préféré le Little-endian ou les poids les plus faibles sont en tête c'est-à-dire dans l’adressage le plus faible.

Attention l’unité adressage est l’octet.
Donc si vous visualisez un octet en hexa ou en binaire il n’y a aucune inversion des bits ou du demi octet dans cette unité c'est à dire dans l'octet.
En little-endian les nombres ont des octets qui sont placés en ordre de poids, du poids le plus faible à la plus faible adresse jusqu’au poids le plus fort dans l’adresse la plus forte.

Enfin pour retrouver les nombres dans l’ordre dans lesquels on les lit en occident il suffit d’utiliser par exemple :
Soit Bin(..)
Soit Hex(..)

Resultat$ = Hex(Valeur.q [, Type])
Description
Convertit un entier en une valeur hexadécimale.
Arguments
Valeur.q Un entier de type 'quad'.
Type (optionnel) #PB_Quad : valeur sera traitée en quad (0 à 18446744073709551615)
#PB_Byte : La valeur est un octet (8-bit) allant de 0 à 255
#PB_Ascii : La valeur est un octet (8-bit) allant de 0 à 255
#PB_Word : La valeur est un word (16-bit) allant de 0 à 65535
#PB_Unicode: La valeur est un word (16-bit) allant de 0 à 65535
#PB_Long : La valeur est un long (32-bit) allant de 0 à 4294967295

Exemples sous PB560 en unicode

On peut remarquer dans le dump de la variable numer l’ordre des octets en parfait concordance avec la définition de litte-endian.

Code : Tout sélectionner

structure NUM
  VB.B
  VW.w
  VL.l
  Vq.q
  VF.F
  VD.D
  VS.s{18}
 EndStructure 

macro _HEX (__ad,lng,flag)
;  CompilerIf #PB_Compiler_Unicode =0
;     ; en ascii  le nombre d'octets est le même que la longueur en caractères lng=lng
;   CompilerElse
;     ; en unicode le nombre d'octets  est double de la longueur en caractères
;     lng=lng*2
;   CompilerEndIf
  sort.s=""
  hexs.s=""
  cart$=""
  If flag=0
; ;     teth.s=" Unité     0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0  1"+#LF$
      teth.s="Adresse___00_01_02_03_04_05_06_07_08_09_0A_0B_0C_0D_0E_0F_10_11_12_13_14_15_16_17_18_19_1A_1B_1C_1D_1E_1F_20_21_22_23_24_25_26_27_28_29_2A_2B_2C_2D_2E_2F_30_31_32_33_34_35_36_37_38_39_3A_3B_3C_3D_3E_3F_40_41"
      sort.s=Left(teth,(lng-1)*3+12)+"        ASCII"+#LF$
    flag=1
  EndIf
  For i=0 To lng-1
    num.c=PeekA(__ad+i)
    If Chr(num)<" " or num>128
      cart$=cart$+"."
    Else
      cart$=cart$+Chr(num)
    EndIf
    hexs.s=hexs.s+RSet(Hex(num),2,"0")+"_"
  Next
    sort.s+RSet(Hex(__ad),8,"0")+"  "+hexs+"    "+cart$+#LF$
    debug sort
endmacro

lng=16
define numer.num
numer\VB=$EF
numer\VW=$1234
numer\VL=$56789ABC
numer\Vq=$0123456789ABCDEF
numer\VS="Jean-Claude Durand"
flg=0
__ad=numer
_hex(__ad,lng,flg)
    debug "VB="+hex(numer\VB,#PB_Byte  )
    debug "VW="+hex(numer\VW,#PB_Word  )
    debug "VL="+hex(numer\Vl,#PB_Long  )
    debug "VQ="+hex(numer\Vq,#PB_Quad  )
    __ad=@numer\VS 
    lng=36  ; doubler le nombre d'octets en unicode donner le nombre de caractère en ascii
    flg=0
_Hex(__ad,lng,flg)    

A+
Il est fort peu probable que les mêmes causes ne produisent pas les mêmes effets.(Einstein)
Et en logique positive cela donne.
Il est très fortement probable que les mêmes causes produisent les mêmes effets.
Répondre