Konvertieren Sie eine Textdatei mit Bits in eine Binärdatei

Konvertieren Sie eine Textdatei mit Bits in eine Binärdatei

Ich habe eine Datei instructions.txtmit dem Inhalt:

00000000000000000000000000010011
00000010110100010010000010000011
00000000011100110000001010110011
00000000011100110000010000110011
00000000011100110110010010110011
00000000000000000000000000010011

Wie kann ich eine Binärdatei instructions.binmit denselben Daten wie erstellen instructions.txt? Mit anderen Worten, die .binDatei sollte dieselben 192 Bits haben wie die .txtDatei selbst, mit 32 Bits pro Zeile. Ich verwende Bash unter Ubuntu Linux. Ich habe versucht, es zu verwenden, xxd -b instructions.txtaber die Ausgabe ist viel länger als 192 Bits.

Antwort1

Oneliner zum Konvertieren von 32-Bit-Zeichenfolgen aus Einsen und Nullen in entsprechende Binärzahlen:

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

Was es macht:

  • perl -nedurchläuft jede Zeile der Eingabedatei, die über STDIN ( instructions.txt) bereitgestellt wird
  • pack("B32", $_)nimmt eine Zeichenfolgenliste mit 32 Bits ( $_die wir gerade von STDIN gelesen haben) und konvertiert sie in einen Binärwert (Sie können dies alternativ verwenden, "b32"wenn Sie innerhalb jedes Bytes eine aufsteigende statt einer absteigenden Bitreihenfolge wünschen; siehe perldoc -f packfür weitere Details)
  • printwürde dann den konvertierten Wert an STDOUT ausgeben, den wir dann an unsere Binärdatei weiterleiteninstructions.bin

verifizieren:

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

Antwort2

Das Hinzufügen der -rOption (Reverse Mode) xxd -bfunktioniert nicht wie vorgesehen, da xxd die Kombination dieser beiden Flags einfach nicht unterstützt (es ignoriert, -bwenn beide angegeben sind). Stattdessen müssen Sie die Bits zuerst selbst in Hex umwandeln. Zum Beispiel so:

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

Vollständige Erklärung:

  • Der Teil in den Klammern erstellt ein bcSkript. Es setzt zuerst die Eingabebasis auf binär (2) und die Ausgabebasis auf hexadezimal (16). Danach seddruckt der Befehl den Inhalt von instructions.txtmit einem Semikolon zwischen jeder Gruppe von 4 Bits aus, was 1 Hexadezimalziffer entspricht. Das Ergebnis wird in weitergeleitet bc.
  • Das Semikolon ist ein Befehlstrennzeichen in bc, daher druckt das Skript lediglich alle eingegebenen Ganzzahlen wieder aus (nach der Basiskonvertierung).
  • Die Ausgabe bcist eine Folge von Hex-Ziffern, die mit dem üblichen in eine Datei konvertiert werden kann xxd -r -p.

Ausgabe:

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

Antwort3

Meinursprüngliche Antwortwar falsch – kann weder „ oder“ mit … xxdakzeptieren .-p-r-b

Da die anderen Antworten praktikabel sind und im Interesse von „ein anderer Weg", wie wäre es mit folgendem:

Eingang

$ cat instructions.txt
00000000000000000000000000010011
00000010110100010010000010000011
00000000011100110000001010110011
00000000011100110000010000110011
00000000011100110110010010110011
00000000000000000000000000010011

Ausgabe

$ 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

Bash-Pipeline:

cat instructions.txt \
    | tr -d $'\n' \
    | while read -N 4 nibble; do 
        printf '%x' "$((2#${nibble}))"; \
      done \
    | xxd -r -p \
    > instructions.bin
  • cat- unnötig, wird aber der Übersichtlichkeit halber verwendet
  • tr -d $'\n'- alle Zeilenumbrüche aus der Eingabe entfernen
  • read -N 4 nibble- lesengenau4× Zeichen in die nibbleVariable
  • printf '%x' "$((2#${nibble}))"Konvertieren Sie das Nibble von binär in 1× Hex-Zeichen
    • $((2#...))- Konvertieren Sie den angegebenen Wert von der Basis 2 (binär) in die Basis 10 (dezimal)
    • printf '%x'- formatiert den angegebenen Wert von Basis 10 (dezimal) nach Basis 16 (hexadezimal)
  • xxd -r -p- reverse ( -r) einen einfachen Dump ( -p) - von hexadezimal nach rohem Binär

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
  • Ein nicht zitierterhierdoc( << EOF) wird verwendet, um Inhalte in den Python-Code zu bekommen
    • Dies ist nicht effizient, wenn der Input groß wird
  • catund tr- wird verwendet, um eine saubere (einzeilige) Eingabe zu erhalten
  • range(0, len(d), 8)- Holen Sie sich eine Liste mit Zahlen von 0 bis zum Ende der Zeichenfolge d, wobei Sie jeweils 8 Zeichen lang sind.
  • chr(int(d[i:i+8],2))- Konvertieren Sie den aktuellen Slice ( d[i:i+8]) von Binär in Dezimal ( int(..., 2)) und dann in ein Rohzeichen ( chr(...))
  • [ x for y in z]-Listenverständnis
  • ''.join(...)- Konvertieren Sie die Liste der Zeichen in eine einzelne Zeichenfolge
  • print(...)- Druck es

Antwort4

Binärdateien trennen Zeilen nicht durch Zeilenumbruchzeichen. Binärdateien haben keine Trennzeichen; es ist nur die eine Datei mit einer Reihe von 0 und 1, die auf einem Gerät gespeichert ist und in Sektoren angeordnet ist, die durch eine Dateizuordnungstabelle oder eine ähnliche Zuordnung gesteuert werden, um ihr Bedeutung zu verleihen.

Sie können die Textdatei entweder unverändert in eine Binärdatei mit einem Ergebnis von 192 Bit (24 Byte) konvertieren oder nach jeder 32-Bit-Sequenz ein Zeilenumbruchzeichen hinzufügen, um eine Datei mit 6 zusätzlichen Byte zu erhalten.

Der folgende Code gibt Ihnen wie gewünscht eine 192-Bit-Datei:

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

Alternativ können Sie jeweils 8 Bits lesen, wenn Sie keinen zusätzlichen Code zum Auffüllen wünschen (4-Byte-Zeilen in der Textdatei).

Getestet auf Ubuntu 16.04.7

verwandte Informationen