Обычно я выполняю такие вещи на C ++, но я использую python для написания быстрого скрипта, и я столкнулся с стеной.
Если у меня есть двоичный список (или какой-либо другой python хранит результат «fread»). Я могу получить доступ к отдельным байтам в нем с помощью: buffer [0], buffer [1] и т. Д.
Мне нужно изменить байты [8-11], чтобы сохранить новый 32-битный размер файла (читайте: там уже есть файл, мне нужно его обновить). В C ++ я бы просто получил указатель на местоположение и бросил его для хранения целого числа, но с помощью python я вдруг понял, что понятия не имею, как это сделать.
Как я могу обновить 4 байта в моем буфере в определенном месте, чтобы сохранить значение целого числа в python?
<Сильный> ИЗМЕНИТЬ
Я собираюсь добавить больше, потому что я не могу понять это из решений (хотя я вижу, что они на правильном пути).
Прежде всего, я на python 2.4 (и не могу обновлять, большие корпоративные серверы) - так что, по-видимому, ограничивает мои варианты. Извините, что не упоминал об этом раньше, я не знал, что у него было так много возможностей.
Во-вторых, давайте сделаем это сверхпростым.
Допустим, у меня есть двоичный файл с именем «myfile.binary» с пятибайтовым содержимым «4C53535353» в шестнадцатеричном формате - это эквивалентно представлению ascii для букв «L и 4xS», находящихся в файле только один.
Если я сделаю:
f = open('myfile.binary', 'rb')
contents = f.read(5)
содержимое должно (из ответа Свена Марнаха) содержать пятибайтную неизменяемую строку.
Используя только объекты Python 2.4, как я могу изменить 4 S, хранящихся в «содержимом», на произвольное целочисленное значение? То есть дайте мне строку кода, которая может содержать содержимое байтовых индексов [1-4], содержит 32-битное целое число «myint» со значением 12345678910.
Вам нужна эта функция:
struct.pack_into(fmt, buffer, offset, v1, v2, ...)
Он задокументирован на http://docs.python.org/library/struct.html рядом с вершиной.
Пример кода:
import struct
import ctypes
data=ctypes.create_string_buffer(10)
struct.pack_into(">i", data, 5, 0x12345678)
print list(data)
Similar posting: Python: How to pack different types of data into a string buffer using struct.pack_into
EDIT: Added a Python 2.4 compatible example:
import struct
f=open('myfile.binary', 'rb')
contents=f.read(5)
data=list(contents)
data[0:4]=struct.pack(">i", 0x12345678)
print data
Посмотрите Структурировать модуль. Вам нужна функция pack
.
РЕДАКТИРОВАТЬ:
Код:
import struct
s = "LSSSS" # your string
s = s[0] + struct.pack('
Вывод:
L╙☻ЦI
struct.pack
should be available in Python2.4.
Ваш номер «12345678910» не может быть упакован в 4 байта, я немного его сократил.
Результатом file.read ()
является строка в Python, и она неизменна. В зависимости от контекста задачи, которую вы пытаетесь выполнить, существуют различные решения проблемы.
Один использует массив
модуль : читайте файл напрямую как массив из 32-битных целых чисел. Вы можете изменить этот массив и записать его обратно в файл.
with open("filename") as f:
f.seek(0, 2)
size = f.tell()
f.seek(0)
data = array.array("i")
assert data.itemsize == 4
data.fromfile(f, size//4)
data[2] = new_value
# use data.tofile(g) to write the data back to a new file g
Следующее - это просто демонстрация для вас, чтобы понять, что на самом деле происходит, когда четыре байта преобразуются в целое число. Предположим, у вас есть номер: 15213
Decimal: 15213
Binary: 0011 1011 0110 1101
Hex: 3 B 6 D
В малоинтенсивных системах (например, на компьютерах x86) это число может быть представлено с использованием length-4 bytearray как: b "\ x6d \ x3b \ x00 \ x00"
или b "m; \ x00 \ x00 "
, когда вы печатаете его на экране, чтобы преобразовать четыре байта в целое число, мы просто делаем немного базового преобразования, которое в этом случае:
sum(n*(256**i) for i,n in enumerate(b"\x6d\x3b\x00\x00"))
Это дает вам результат: 15213