web-dev-qa-db-fra.com

convertir un fichier texte en bits binaire

J'ai un fichier instructions.txt avec le contenu:

00000000000000000000000000010011
00000010110100010010000010000011
00000000011100110000001010110011
00000000011100110000010000110011
00000000011100110110010010110011
00000000000000000000000000010011

Comment créer un fichier binaire instructions.bin avec les mêmes données que instructions.txt En d'autres termes, le fichier .bin doit avoir les mêmes 192 bits que le fichier .txt, avec 32 bits par ligne. J'utilise bash sur Ubuntu Linux. J'essayais d'utiliser xxd -b instructions.txt mais la sortie est bien plus longue que 192 bits.

10
dopamane

oneliner pour convertir les chaînes de 32 bits de uns et de zéros en fichiers binaires correspondants:

$ Perl -ne 'print pack("B32", $_)' < instructions.txt > instructions.bin

ce qu'il fait:

  • Perl -ne va parcourir chaque ligne du fichier d'entrée fourni sur STDIN (instructions.txt)
  • pack("B32", $_) prendra une liste de chaînes de 32 bits ($_ que nous venons de lire dans STDIN) et la convertira en valeur binaire (vous pouvez également utiliser "b32" si vous voulez un ordre croissant des bits dans chaque octet au lieu d'un ordre décroissant; voir perldoc -f pack pour plus d'informations. détails)
  • print afficherait alors cette valeur convertie en STDOUT, que nous redirigerons ensuite vers notre fichier binaire instructions.bin

vérifier:

$ hexdump -Cv instructions.bin
00000000  00 00 00 13 02 d1 20 83  00 73 02 b3 00 73 04 33  |...... ..s...s.3|
00000010  00 73 64 b3 00 00 00 13                           |.sd.....|
00000018

$ xxd -b -c4 instructions.bin
00000000: 00000000 00000000 00000000 00010011  ....
00000004: 00000010 11010001 00100000 10000011  .. .
00000008: 00000000 01110011 00000010 10110011  .s..
0000000c: 00000000 01110011 00000100 00110011  .s.3
00000010: 00000000 01110011 01100100 10110011  .sd.
00000014: 00000000 00000000 00000000 00010011  ....
5
Matija Nalis

L'ajout de l'option -r (mode inverse) à xxd -b ne fonctionne pas comme prévu, car xxd ne prend tout simplement pas en charge la combinaison de ces deux indicateurs (il ignore -b si les deux sont indiqués). Au lieu de cela, vous devez d'abord convertir les bits pour vous en servir. Par exemple comme ceci:

( echo 'obase=16;ibase=2'; sed -Ee 's/[01]{4}/;\0/g' instructions.txt ) | bc | xxd -r -p > instructions.bin

Explication complète:

  • La partie entre parenthèses crée un script bc. Il définit d'abord la base d'entrée sur binaire (2) et la base de sortie sur hexadécimale (16). Après cela, la commande sed imprime le contenu de instructions.txt avec un point-virgule entre chaque groupe de 4 bits, ce qui correspond à 1 chiffre hexadécimal. Le résultat est transféré dans bc.
  • Le point-virgule est un séparateur de commandes dans bc. Le script n'imprime donc que tous les entiers en entrée (après la conversion de base).
  • La sortie de bc est une séquence de chiffres hexadécimaux, qui peuvent être convertis en un fichier avec le xxd -r -p habituel.

Sortie:

$ hexdump -Cv instructions.bin
00000000  00 00 00 13 02 d1 20 83  00 73 02 b3 00 73 04 33  |...... ..s...s.3|
00000010  00 73 64 b3 00 00 00 13                           |.sd.....|
00000018
$ xxd -b -c4 instructions.bin
00000000: 00000000 00000000 00000000 00010011  ....
00000004: 00000010 11010001 00100000 10000011  .. .
00000008: 00000000 01110011 00000010 10110011  .s..
0000000c: 00000000 01110011 00000100 00110011  .s.3
00000010: 00000000 01110011 01100100 10110011  .sd.
00000014: 00000000 00000000 00000000 00010011  ....
8
nomadictype

Ma réponse originale était incorrecte - xxd ne peut accepter ni -p ni -r avec -b...

Etant donné que les autres réponses sont réalisables, et dans l’intérêt de ", une autre manière ", que diriez-vous de ce qui suit:

Contribution

$ cat instructions.txt
00000000000000000000000000010011
00000010110100010010000010000011
00000000011100110000001010110011
00000000011100110000010000110011
00000000011100110110010010110011
00000000000000000000000000010011

Sortie

$ hexdump -Cv < instructions.bin
00000000  00 00 00 13 02 d1 20 83  00 73 02 b3 00 73 04 33  |...... ..s...s.3|
00000010  00 73 64 b3 00 00 00 13                           |.sd.....|
00000018

Pipeline Bash:

cat instructions.txt \
    | tr -d $'\n' \
    | while read -N 4 nibble; do 
        printf '%x' "$((2#${nibble}))"; \
      done \
    | xxd -r -p \
    > instructions.bin
  • cat - inutile, mais utilisé pour plus de clarté
  • tr -d $'\n' - supprime toutes les nouvelles lignes de l'entrée
  • read -N 4 nibble - lire exactement 4 × caractères dans la variable nibble
  • printf '%x' "$((2#${nibble}))" convertit le quartet de binaire en 1 × caractère hexadécimal
    • $((2#...)) - convertit la valeur donnée en base 2 (binaire) en base 10 (décimale)
    • printf '%x' - formate la valeur donnée de la base 10 (décimale) à la base 16 (hexadécimale)
  • xxd -r -p - inverse (-r) un vidage simple (-p) - de l'hexadécimal au binaire brut

Python:

python << EOF > instructions.bin
d = '$(cat instructions.txt | tr -d $'\n')'
print(''.join([chr(int(d[i:i+8],2)) for i in range(0, len(d), 8)]))
EOF
  • Un heredoc non entre guillemets (<< EOF) est utilisé pour obtenir du contenu dans le code Python
    • Ce n'est pas efficace si l'entrée devient grande
  • cat et tr - utilisé pour obtenir une entrée propre (une ligne)
  • range(0, len(d), 8) - Obtenir une liste de nombres de 0 à la fin de la chaîne d, en passant à 8 × caractères à la fois.
  • chr(int(d[i:i+8],2)) - convertit la tranche actuelle (d[i:i+8]) de binaire en décimal (int(..., 2)), puis en un caractère brut (chr(...))
  • [ x for y in z] - liste compréhension
  • ''.join(...) - convertit la liste de caractères en une seule chaîne
  • print(...) - l'imprimer
2
Attie

Vous pouvez aussi bien essayer de poster ceci sur le site CodeGolf SE, mais voici ma version alternative de Python (juste pour le défi):

python -c "import sys,struct;[sys.stdout.buffer.write(struct.pack('!i',int(x,2)))for x in sys.stdin]" \
< input.txt > output.bin

En supposant que input.txt contient vos données, elles sont formatées à 32 caractères par ligne.

Ceci utilise le paquet struct de Python 3 et l’écriture/la lecture sur stdin/out. (En Python 2, cela aurait été plus court).

1
wvxvw