Binaire Hexa :-S Un petit soutient svp

cs_MrDimanche Messages postés 16 Date d'inscription mercredi 25 juillet 2007 Statut Membre Dernière intervention 16 avril 2008 - 25 juil. 2007 à 09:03
ctx_man Messages postés 285 Date d'inscription mardi 28 décembre 2004 Statut Membre Dernière intervention 20 janvier 2013 - 25 juil. 2007 à 11:53
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

BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
25 juil. 2007 à 09:49
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++
0
ctx_man Messages postés 285 Date d'inscription mardi 28 décembre 2004 Statut Membre Dernière intervention 20 janvier 2013 3
25 juil. 2007 à 10:37
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 )
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
25 juil. 2007 à 11:44
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++
0
ctx_man Messages postés 285 Date d'inscription mardi 28 décembre 2004 Statut Membre Dernière intervention 20 janvier 2013 3
25 juil. 2007 à 11:53
Lol, l'artillerie lourde, on sort l'asm !
0
Rejoignez-nous