[Divers] Inverser octets tous les 2 n

Inverser octets tous les 2 n [Divers] - Divers - Programmation

Marsh Posté le 13-08-2010 à 19:36:33    

Bonsoir à tous.
 
 Voila, je ne connais strictement rien en dev aussi merci de me fusiller sur place ou bien de m'aider un poil ^^
 
 Voici ce que je souhaiterai obtenir, et ce, avec un langage ou un outil tout prêt (ouais je rêve) accessible pour un gogol comme moi.
 
 Je possède un fichier binaire qui doit au final ressembler à cela :
 
Source:
bb 1b 53 c4 bc 11 45 c4 11 11 c3 bc 11 b1 1c 11  
 
Destination:
1b bb c4 53 11 bc c4 45 11 11 bc c3 b1 11 11 1c  
 
 Grosso modo, j'ai besoin de swapper 2 octets entre eux tous les 2 octets ... pas clair ? .. normal je pige pas grand chose ^^
 
 Aussi si quelqu'un pouvait avoir la bonté de me répondre sans me proposer d'aller jouer dans le mixer ce serait fun.  :lol:


Message édité par yoplait21 le 13-08-2010 à 19:36:48
Reply

Marsh Posté le 13-08-2010 à 19:36:33   

Reply

Marsh Posté le 13-08-2010 à 20:22:01    

C'est pas trop autorisé par la charte ta requête, mais bon je suis de bonne humeur donc voilà un petit code en C qui devrait marcher correctement, je l'ai pas plus testé que ça mais ça a l'air de pas planter donc on va pas se plaindre :o
 

Code :
  1. #include <stdio.h>
  2. #include <fcntl.h>
  3.  
  4. # define BUF_SIZE 512
  5.  
  6. void        swap_bytes(char *filename)
  7. {
  8.    char    buffer[BUF_SIZE];
  9.    char    curByte;
  10.    int     fd;
  11.    int     bytesRead;
  12.    size_t  posBuffer;
  13.  
  14.    fd = open(filename, O_RDWR | O_BINARY);
  15.    if (fd == -1)
  16.    {
  17.        printf("Erreur: Le fichier %s ne peut etre ouvert\n", filename);
  18.        return;
  19.    }
  20.    while ((bytesRead = read(fd, buffer, BUF_SIZE)) > 0)
  21.    {
  22.        posBuffer = 0;
  23.        while (posBuffer + 1 < bytesRead)
  24.        {
  25.            curByte = buffer[posBuffer];
  26.            buffer[posBuffer] = buffer[posBuffer + 1];
  27.            buffer[posBuffer + 1] = curByte;
  28.            posBuffer += 2;
  29.        }
  30.        lseek(fd, -bytesRead, SEEK_CUR);
  31.        write(fd, buffer, bytesRead);
  32.    }
  33.    close(fd);
  34. }
  35.  
  36.  
  37. int         main(int argc, char **argv)
  38. {
  39.    if (argc == 1)
  40.        printf("Usage: %s fichier\n", argv[0]);
  41.    else
  42.        swap_bytes(argv[1]);
  43.    return (0);
  44. }


 
Si tu traites de gros fichiers, hésites pas a changer le # define BUF_SIZE 512 par un truc beaucoup plus gros genre # define BUF_SIZE 1048576, ça bourrinera moins le disque dur et tu gagneras en rapidité :o


---------------
"I can cry like Roger. It's just a shame I can't play like him" - Andy Murray, 2010
Reply

Marsh Posté le 13-08-2010 à 21:44:46    

Merci beaucoup pour ton aide,
 
 je teste cela de suite

Reply

Marsh Posté le 13-08-2010 à 21:44:49    

Code :
  1. cat test.txt | perl -e 'my $v = <STDIN>; $v =~ s/([^ \n]+) ([^ \n]+)/$2 $1/g; print $v;'

Reply

Marsh Posté le 13-08-2010 à 21:58:12    

Funky ^^
 
 j'ai voulu compiler sous linux, et j'ai lu l'histoire d'un mec qui disait que sa belle soeur par alliance de son oncle lui avait dit que O_BINARY n'était pas nécessaire sous système linux because pas de distingo entre text et binaire .. en plus ça compilait pas .. bref  
 
 testé sans O_BINARY ... fichier entrée = 2mo fichier sortie 4go ^^
 
 
 Je télécharge de ce pas la trial de vs2010 ^^


Message édité par yoplait21 le 13-08-2010 à 21:58:24
Reply

Marsh Posté le 13-08-2010 à 22:04:01    

regexp42 a écrit :

Code :
  1. cat test.txt | perl -e 'my $v = <STDIN>; $v =~ s/([^ \n]+) ([^ \n]+)/$2 $1/g; print $v;'



 
 Perl fonctionne en binaire ou octal ? je doute (mais je peux me tromper of course)

Reply

Marsh Posté le 13-08-2010 à 23:00:09    

Y'a sûrement moyen de faire fonctionner perl pour manipuler directement les octets de ton fichier :o
 
O_BINARY je l'ai mis par sécurité histoire qu'il fasse pas du khakha mais en général ouais c'est pas utile :jap:


---------------
"I can cry like Roger. It's just a shame I can't play like him" - Andy Murray, 2010
Reply

Marsh Posté le 14-08-2010 à 01:25:04    

yoplait21 a écrit :


 
 Perl fonctionne en binaire ou octal ? je doute (mais je peux me tromper of course)


 
Essaye ça alors :
 

Code :
  1. cat file.bin | perl -e 'my $v = <STDIN>; $v =~ s/(..)(..)/$2$1/g; print $v;'

Reply

Marsh Posté le 14-08-2010 à 08:12:07    

Merci mais rien ne s'affiche et aucune modification sur le fichier d'entrée ( je n'ai pas spécifié de sortie mais vu la commande il doit s'écraser sur l'entrée non ? )

Reply

Marsh Posté le 14-08-2010 à 09:49:57    

Tu veux juste swapper les octets deux par deux? si tu es sous linux, dd est prévu pour cela:
dd if=inputfile of=outputfile conv=swab
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 14-08-2010 à 09:49:57   

Reply

Marsh Posté le 14-08-2010 à 10:18:35    

Alors ça ça le fait ^^
 
 cela fonctionne merci bien ^^

Reply

Marsh Posté le 14-08-2010 à 10:23:15    

yoplait21 a écrit :

Merci mais rien ne s'affiche et aucune modification sur le fichier d'entrée ( je n'ai pas spécifié de sortie mais vu la commande il doit s'écraser sur l'entrée non ? )


 
Non il "affiche" sur stdout, et comme c'est du binaire il vaut mieux rediriger ça dans un fichier. Ca fonctionne chez moi :
 
 

Citation :

$> hexdump file.bin
0000000 457f 464c 0102 0001 0000
$> cat file.bin | perl -e 'my $v = <STDIN>; $v =~ s/([^ \n]+) ([^ \n]+)/$2 $1/g; print $v;' > file2.bin
$> hexdump file2.bin
0000000 7f45 4c46 0201 0100 0000
$>


Reply

Marsh Posté le 14-08-2010 à 11:21:39    

Euh, tu es sur que ton code perl fonctionne encore si tu as des \n dans ton binaire? :whistle:
En plus, à lire ton expression régulière, ça peut pas marcher du tout
/([^ \n]+) ([^ \n]+)/ ça va matcher sur texte composé de deux caractères séparés par du blanc, mais certainement pas le binaire voulu (ou il y a pas de blancs, etc).
Un petit test pour s'en convaincre:

Code :
  1. #!/usr/bin/perl
  2. use warnings;
  3. use strict;
  4.  
  5. my $v = join '', (0x01,0x02,0x03,0x04);
  6. $v =~ s/([^ \n]+) ([^ \n]+)/$2 $1/g;
  7. map {printf "%#.2x ", $_} split //, $v;

En sortie, on a la même chose qu'en entrée, rien n'a été swappé des 4 octets successifs de valeur 1 2 3 et 4.
A la limite, tu aurais écrit s/(.)(.)/$2$1/g, ça aurait pu fonctionner (a la coupure de fin de ligne pour une ligne de longueur impaire près).
Il y a des techniques en perl pour faire ce type de conversion, mais elles reposent plutôt sur pack/unpack, et une lecture qui ne se fait pas ligne à ligne (contrairement à ce que fait ici le my $v = <STDIN> )
A+,

Message cité 1 fois
Message édité par gilou le 14-08-2010 à 11:57:22

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 14-08-2010 à 13:25:13    

gilou a écrit :

Euh, tu es sur que ton code perl fonctionne encore si tu as des \n dans ton binaire? :whistle:


 
Oui j'me suis vautré dans mon copier coller, c'est plutôt "s/(.)(.)/$2$1/g" la regex.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed