converter arquivo de texto de bits em arquivo binário

converter arquivo de texto de bits em arquivo binário

Eu tenho um arquivo instructions.txtcom o conteúdo:

00000000000000000000000000010011
00000010110100010010000010000011
00000000011100110000001010110011
00000000011100110000010000110011
00000000011100110110010010110011
00000000000000000000000000010011

Como posso criar um arquivo binário instructions.bincom os mesmos dados do instructions.txt. Em outras palavras, o .binarquivo deve ter os mesmos 192 bits que estão no .txtarquivo, com 32 bits por linha. Estou usando o bash no Ubuntu Linux. Eu estava tentando usar, xxd -b instructions.txtmas a saída é muito maior que 192 bits.

Responder1

oneliner para converter strings de uns e zeros de 32 bits em binário correspondente:

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

o que faz:

  • perl -neirá iterar através de cada linha do arquivo de entrada fornecido em STDIN ( instructions.txt)
  • pack("B32", $_)pegará uma lista de strings de 32 bits ( $_que acabamos de ler em STDIN) e a converterá em valor binário (você poderia alternativamente usar "b32"se quisesse uma ordem crescente de bits dentro de cada byte em vez de uma ordem decrescente de bits; veja perldoc -f packpara mais detalhes)
  • printgeraria então esse valor convertido para STDOUT, que então redirecionamos para nosso arquivo binárioinstructions.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  ....

Responder2

Adicionar a -ropção (modo reverso) a xxd -bnão funciona como esperado, porque xxd simplesmente não suporta a combinação desses dois sinalizadores (ele ignora -bse ambos forem fornecidos). Em vez disso, você deve primeiro converter os bits em hexadecimal. Por exemplo assim:

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

Explicação completa:

  • A parte entre parênteses cria um bcscript. Primeiro ele define a base de entrada como binária (2) e a base de saída como hexadecimal (16). Depois disso, o sedcomando imprime o conteúdo instructions.txtcom ponto e vírgula entre cada grupo de 4 bits, o que corresponde a 1 dígito hexadecimal. O resultado é canalizado para bc.
  • O ponto e vírgula é um separador de comando bc, portanto, tudo o que o script faz é imprimir todos os números inteiros de entrada (após a conversão da base).
  • A saída de bcé uma sequência de dígitos hexadecimais, que pode ser convertida em um arquivo com o formato xxd -r -p.

Saída:

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

Responder3

Meuresposta originalestava incorreto - xxdnão posso aceitar um -pou -rcom -b...

Dado que as outras respostas são viáveis, e no interesse de "outra maneira", que tal o seguinte:

Entrada

$ cat instructions.txt
00000000000000000000000000010011
00000010110100010010000010000011
00000000011100110000001010110011
00000000011100110000010000110011
00000000011100110110010010110011
00000000000000000000000000010011

Saída

$ 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- desnecessário, mas usado para maior clareza
  • tr -d $'\n'- remova todas as novas linhas da entrada
  • read -N 4 nibble- lerexatamente4× caracteres na nibblevariável
  • printf '%x' "$((2#${nibble}))"converter o nibble de binário para 1× caractere hexadecimal
    • $((2#...))- converter o valor fornecido da base 2 (binária) para a base 10 (decimal)
    • printf '%x'- formatar o valor fornecido da base 10 (decimal) para a base 16 (hexadecimal)
  • xxd -r -p- inverter ( -r) um despejo simples ( -p) - de hexadecimal para binário bruto

Pitão:

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
  • Um não citadoheredoc( << EOF) é usado para inserir conteúdo no código Python
    • Isto não é eficiente se a entrada se tornar grande
  • cate tr- usado para obter uma entrada limpa (uma linha)
  • range(0, len(d), 8)- obtenha uma lista de números de 0 ao final da string d, avançando 8× caracteres por vez.
  • chr(int(d[i:i+8],2))- converter a fatia atual ( d[i:i+8]) de binário para decimal ( int(..., 2)) e depois para um caractere bruto ( chr(...))
  • [ x for y in z]-compreensão da lista
  • ''.join(...)- converter a lista de caracteres em uma única string
  • print(...)- imprima

Responder4

arquivos binários não separam linhas com caracteres de nova linha. Arquivos binários não possuem delimitadores; é apenas um arquivo com vários 0 e 1, armazenado em algum dispositivo organizado em setores controlados pela tabela de alocação de arquivos ou mapeamento semelhante para dar significado.

Você pode converter o arquivo de texto como está, para binário, resultando em 192 bits (24 bytes) ou adicionar um caractere de nova linha após cada sequência de 32 bits para fornecer um arquivo com 6 bytes extras.

O código abaixo fornece um arquivo de 192 bits, conforme solicitado:

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

A alternativa é ler 8 bits por vez se não quiser código extra para preenchimento (linhas de 4 bytes no arquivo de texto)

Testado no Ubuntu 16.04.7

informação relacionada