Binaire Hexa :-S Un petit soutient svp

Signaler
Messages postés
16
Date d'inscription
mercredi 25 juillet 2007
Statut
Membre
Dernière intervention
16 avril 2008
-
Messages postés
285
Date d'inscription
mardi 28 décembre 2004
Statut
Membre
Dernière intervention
20 janvier 2013
-
Bonjour, voila ce qui m'amène.
Je dois lire un fichier de données binaire, et le convertir. Mais si j'ai une petite expérience en c, c'est la première fois que je fais ce genre de travail, et je m'embrouille.
Le fichier se trouve generalement en mots de 32 bits, mais pas toujours, et mon programme ne lit que par mots de 32 bits (que je met dans un buffer[]). Mais mon plus gros problème est que un mot dont la valeur est 0bf6752e sort tel que 2e75f60b, soit chaque octet à l'envers.

Ce qui m'amène à mes deux questions : comment faire pour mon programme lise plutôt octets par octets, ou même bit par bit (certaines données sont sur 1 bit), et comment inverser chaque mots pour retrouver la bonne valeur ? Merci pour votre aide, je sais qu'ainsi ce n'est pas très clair, mais je joint le programme que j'ai récupéré, et j'ai bricolé quelques solution, mais ça ne marche pas toujours :

/* fread example: read a complete file */
#include <stdio.h>
#include <stdlib.h>

//fonction qui permet d'inverser les octet dans 32 bits, mais ne marche pas toujours
int reverseByte(int buffer)
    {
   int tamp=0;
  tamp=16777216*(buffer-256*(int)(buffer/256));
  tamp=tamp+65536*((int)(buffer/256)-(256*(int)(buffer/65536)));
  tamp=tamp+256*((int)(buffer/65536)-(256*(int)(buffer/16777216)));
  tamp=tamp+(int)(buffer/16777216);
  return tamp;
     }

int main () {
  FILE * pFile;
  long lSize;
  int * buffer;
  size_t result;
  int i,n,MainN;
  pFile = fopen ( "/Users/nicole/Nemo/nemo_ph1_R00000018_F00000005.dat" , "rb" );
  if (pFile==NULL) {fputs ("File error",stderr); exit (1);}

  // obtain file size:
  fseek (pFile , 0 , SEEK_END);
  lSize = ftell (pFile);
  rewind (pFile);

  // allocate memory to contain the whole file:
  buffer = (int*) malloc (sizeof(int)*lSize);
  if (buffer == NULL) {fputs ("Memory error",stderr); exit (2);}

  // copy the file into the buffer:
  result = fread (buffer,1,lSize,pFile);
  if (result != lSize) {fputs ("Reading error",stderr); exit (3);}

  /* the whole file is now loaded in the memory buffer. */
  for(i=0;i<3;i++)
    printf("%.8x\n",buffer[i]);
  // terminate
  //printf("%x\t",(int)(buffer[0])/65536);
  fclose (pFile);
 
 
  buffer[0]=reverseByte(buffer[0]);
  printf("The version date : %d\n",buffer[0]);
  buffer[1]=reverseByte(buffer[1]);
  printf("The size (byte): %d\n",buffer[1]);  //cette partie marche, mais par pour chaques mot :s

 
  free (buffer);
 
 
  return 0;
}

4 réponses

Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
29
tamp=16777216*(buffer-256*(int)(buffer/256));
ce genre de ligne est tout droit issu de VB, en C on a des opérateurs de bits (<< , >>).

Dans tous les cas c'est totalement inutile, les octets ne s'inversent pas dans un fichier.

ciao...
BruNews, MVP VC++
Messages postés
285
Date d'inscription
mardi 28 décembre 2004
Statut
Membre
Dernière intervention
20 janvier 2013

Petite astuce pour retourner un mot super facilement :

char* FileStream; //On va utiliser un pointer de caractère pour lire
int* Buffer;
Buffer = (int*) malloc (sizeof(int)*lSize);
FileStream = (char*)Buffer; //Faire pointer ton char* sur ton Buffer
result = fread (FileStream,1,lSize,pFile);

Et voila, grace a l'arithmétique des pointeurs, ton entier est écrit a l'envers.

En fait ton problème de retournement via d'ailleur de la je pense.
En gros tu écrit des int et tu lit des char, donc si ta mémoire est en adresse forte = poid faible (little-endian si je me trompe pas ce qui est fort probable) alors la lecture en char va t'inverser les données. Puisque dans ton fichier le poids faible est est l'adresse faible et il va se retrouver à l'adresse faible de ton int, qui en mémoire représente le poid fort. (Je doute fortement de la clareté de mes propos la ...)

Enfin bref, si tu lit des mots de 32 bits, alors lit par block de 32 bits.
result = fread (buffer, 4, lSize / 4, pFile);

Si vraiment c'est pas possible et que mon astuce précitée ne fonctionne pas, alors voici comment on fait un retournement normalement

int Retournement(int n)
{
return = ((n & 0xFF000000) >> 24) | ((n & 0x00FF0000) >> 8) | ((n & 0x0000FF00) << 8) | ((n & 0x000000FF) << 24);
}

(en espérant pas me planter :D )
Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
29
Juste pour info:
cpu est cablé en dur pour le faire, imbattable.

__declspec(naked) int __fastcall Retournement(int n)
{
  __asm {
    bswap  ecx
    mov    eax, ecx
    ret   0
  }
}

ciao...
BruNews, MVP VC++
Messages postés
285
Date d'inscription
mardi 28 décembre 2004
Statut
Membre
Dernière intervention
20 janvier 2013

Lol, l'artillerie lourde, on sort l'asm !