Можно ли как-то вставить отдельные биты в новый файл, не создавая временные файлы и не конкатенируя их?
Например, я хочу создать файл из 10 октетов, где первые три установить на 4
, следующие два на 7
и последние пять на 32
.
0000.0100 0000.0100 0000.0100 0000.0111 0000.0111 0010.0000 0100.0000 0010.0000 0010.0000 0010.0000
blockquote>Мне нужно решение, которое позволило бы мне создавать большие файлы, в которых определенные биты повторяются много раз.
Это довольно просто в Python. Можно запустить интерактивный интерпретатор, просто введя python
и сделайте что-то вроде этого:
>>> open("test.bin", "wb").write("\4\4\4\7\7\32\32\32\32\32")
'wb'
означает "открытый файл для записи двоичных данных к нему", просто открывая файл с w
предположит, что Вы хотите записать текст в него.
Обратите внимание, что это восьмеричные числа (\32
0x1a
, или 26)! Они могут также быть шестнадцатеричными (\xff
), и можно сохранить некоторый ввод путем выполнения чего-то вроде этого:
>>> "\x00" * 4 + "\x09"
'\x00\x00\x00\x00\x09'
Нормальный приоритет оператора применяется.
Для большего количества данных можно использовать списки десятичных целых чисел - который я нахожу легче считать и ввести:
>>> d = [1, 2, 3, 4, 5]
>>> ''.join(chr(i) for i in d)
'\x01\x02\x03\x04\x05'
Если Вы предпочитаете использовать python3
, Вы использовали бы bytes()
как это:
>>> bytes([1, 2, 3, 4, 5])
Конечно, 'арифметика' работает, как Вы ожидали бы:
>>> [1, 2, 3] * 2 + [9] * 4 + range(4)
[1, 2, 3, 1, 2, 3, 9, 9, 9, 9, 0, 1, 2, 3]
>>> range(10, 0, -3)
[10, 7, 4, 1]
Двоичный файл, orcal и шестнадцатеричные литералы записаны как это:
0b1100 == 0o14 == 12 == 0xc
(Или 014
если Вы предпочитаете),
Если Вы хотите сделать некоторый сложный материал, открыть файл сначала и затем постепенно писать в него:
>>> f = open("test.bin", "wb")
>>> f.write("\xff" * 100)
>>> for i in range(10):
... f.write("\xff\xfa\x03")
...
>>> f.close()
И если Вы хотите написать сценарий его, можно использовать -c
переключатель для вызова кода непосредственно из командной строки:
python -c "open('test.bin', 'wb').write(''.join(chr(i) for i in [1, 2, 3]))"
В ruby, запись паттерна 10 раз:
File.open('bits','w') do |f|
10.times do
f << ([0x04]*3+[0x07]*2+[0x20]*5).pack('C*')
end
end
Записывая файл в каждую итерацию, мы сохраняем только одну копию битового паттерна в памяти. Таким образом, вы можете записывать файлы любого размера, изменив 10.times
на 10000.times
и т. Д.
Итак, из командной строки:
$ ruby -e "File.open('bits','w'){|f|10.times{f<<([0x04]*3+[0x07]*2+[0x20]*5).pack('C*')}}"
Затем проверьте файл:
$ xxd -b bits
0000000: 00000100 00000100 00000100 00000111 00000111 00100000 .....
0000006: 00100000 00100000 00100000 00100000 00000100 00000100 ..
000000c: 00000100 00000111 00000111 00100000 00100000 00100000 ...
0000012: 00100000 00100000 00000100 00000100 00000100 00000111 ....
0000018: 00000111 00100000 00100000 00100000 00100000 00100000 .
000001e: 00000100 00000100 00000100 00000111 00000111 00100000 .....
0000024: 00100000 00100000 00100000 00100000 00000100 00000100 ..
000002a: 00000100 00000111 00000111 00100000 00100000 00100000 ...
0000030: 00100000 00100000 00000100 00000100 00000100 00000111 ....
0000036: 00000111 00100000 00100000 00100000 00100000 00100000 .
000003c: 00000100 00000100 00000100 00000111 00000111 00100000 .....
0000042: 00100000 00100000 00100000 00100000 00000100 00000100 ..
0000048: 00000100 00000111 00000111 00100000 00100000 00100000 ...
000004e: 00100000 00100000 00000100 00000100 00000100 00000111 ....
0000054: 00000111 00100000 00100000 00100000 00100000 00100000 .
000005a: 00000100 00000100 00000100 00000111 00000111 00100000 .....
0000060: 00100000 00100000 00100000 00100000
См. Документацию для Array.pack здесь .