convertir un archivo de texto de bits a un archivo binario

convertir un archivo de texto de bits a un archivo binario

Tengo un archivo instructions.txtcon el contenido:

00000000000000000000000000010011
00000010110100010010000010000011
00000000011100110000001010110011
00000000011100110000010000110011
00000000011100110110010010110011
00000000000000000000000000010011

¿Cómo puedo crear un archivo binario instructions.bincon los mismos datos que instructions.txt. En otras palabras, el .binarchivo debe tener los mismos 192 bits que tiene .txt, con 32 bits por línea. Estoy usando bash en Ubuntu Linux. Estaba intentando usarlo xxd -b instructions.txtpero la salida es mucho más larga que 192 bits.

Respuesta1

oneliner para convertir cadenas de unos y ceros de 32 bits en el binario correspondiente:

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

Que hace:

  • perl -neiterará a través de cada línea del archivo de entrada proporcionado en STDIN ( instructions.txt)
  • pack("B32", $_)tomará una lista de cadenas de 32 bits ( $_que acabamos de leer de STDIN) y la convertirá a un valor binario (también puede usarla "b32"si desea un orden de bits ascendente dentro de cada byte en lugar de un orden de bits descendente; consulte perldoc -f packpara obtener más detalles)
  • printluego enviaría ese valor convertido a STDOUT, que luego redirigiría a nuestro archivo binarioinstructions.bin

verificar:

$ 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  ....

Respuesta2

Agregar la -ropción (modo inverso) en xxd -brealidad no funciona según lo previsto, porque xxd simplemente no admite la combinación de estos dos indicadores (ignora -bsi se proporcionan ambos). En cambio, primero debes convertir los bits a hexadecimal. Por ejemplo así:

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

Explicación completa:

  • La parte dentro del paréntesis crea un bcguión. Primero establece la base de entrada en binario (2) y la base de salida en hexadecimal (16). Después de eso, el sedcomando imprime el contenido instructions.txtcon un punto y coma entre cada grupo de 4 bits, que corresponde a 1 dígito hexadecimal. El resultado se canaliza a bc.
  • El punto y coma es un separador de comandos en bc, por lo que todo lo que hace el script es imprimir cada número entero de entrada (después de la conversión de base).
  • La salida de bces una secuencia de dígitos hexadecimales, que se puede convertir en un archivo con el formato habitual xxd -r -p.

Producción:

$ 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  ....

Respuesta3

Mirespuesta originalera incorrecto: xxdno puedo aceptar ninguno de los dos -pni -rcon -b...

Dado que las otras respuestas son viables y en interés de "de otra manera", ¿qué tal lo siguiente?

Aporte

$ cat instructions.txt
00000000000000000000000000010011
00000010110100010010000010000011
00000000011100110000001010110011
00000000011100110000010000110011
00000000011100110110010010110011
00000000000000000000000000010011

Producción

$ 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

Tubería de bash:

cat instructions.txt \
    | tr -d $'\n' \
    | while read -N 4 nibble; do 
        printf '%x' "$((2#${nibble}))"; \
      done \
    | xxd -r -p \
    > instructions.bin
  • cat- innecesario, pero usado para mayor claridad
  • tr -d $'\n'- eliminar todas las nuevas líneas de la entrada
  • read -N 4 nibble- leerexactamente4× caracteres en la nibblevariable
  • printf '%x' "$((2#${nibble}))"convertir el nibble de binario a 1× carácter hexadecimal
    • $((2#...))- convertir el valor dado de base 2 (binario) a base 10 (decimal)
    • printf '%x'- formatee el valor dado de base 10 (decimal) a base 16 (hexadecimal)
  • xxd -r -p- invertir ( -r) un volcado simple ( -p) - de hexadecimal a binario sin formato

Pitón:

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 no citadoheredoc( << EOF) se utiliza para introducir contenido en el código Python.
    • Esto no es eficiente si la entrada se vuelve grande.
  • caty tr- usado para obtener una entrada limpia (de una línea)
  • range(0, len(d), 8)- obtener una lista de números desde 0 hasta el final de la cadena d, avanzando 8× caracteres a la vez.
  • chr(int(d[i:i+8],2))- convertir el segmento actual ( d[i:i+8]) de binario a decimal ( int(..., 2)) y luego a un carácter sin formato ( chr(...))
  • [ x for y in z]-comprensión de la lista
  • ''.join(...)- convertir la lista de caracteres en una sola cadena
  • print(...)- Imprímelo

Respuesta4

Los archivos binarios no separan líneas con caracteres de nueva línea. Los archivos binarios no tienen delimitadores; es solo un archivo con un montón de 0 y 1, almacenado en algún dispositivo organizado en sectores controlados por una tabla de asignación de archivos o un mapeo similar para darle significado.

Puede convertir el archivo de texto tal como está a binario, lo que da como resultado 192 bits (24 bytes) o agregar un carácter de nueva línea después de cada secuencia de 32 bits para obtener un archivo con 6 bytes adicionales.

El siguiente código le proporciona un archivo de 192 bits, según lo solicitado:

for x in $(cat file.txt); 
do s=${x:0:32}; 
echo $(printf '%08X' "$((2#$s))"); 
done | xxd -r -p > file.bin

La alternativa es leer 8 bits a la vez si no desea código adicional para el relleno (líneas de 4 bytes en un archivo de texto)

Probado en Ubuntu 16.04.7

información relacionada