Введение
Хранение содержимого файлов двумя способами, один в бинарном виде, другой в виде текста. Если текст хранится в файле, то время чтения из файла приведет к преобразованию текста в типы данных Python. На самом деле даже сохраненные текстовые данные также являются структурой, потому что базовый Python написан на C, структура C, где мы также вызываем.
Lib / struct.py - это модуль, ответственный за выполнение такого структурного преобразования.
методы в структуре
Сначала посмотрите на определение структуры:
__all__ = [
# Functions
'calcsize', 'pack', 'pack_into', 'unpack', 'unpack_from',
'iter_unpack',
# Classes
'Struct',
# Exceptions
'error'
]
Есть 6 методов, 1 исключение.
В основном мы рассматриваем использование этих 6 методов:
имя метода | эффект |
---|---|
struct.pack(format, v1, v2, ...) | Возвращает объект bytes, содержащий строку формата в соответствии с форматомformatупакованное значениеv1, v2, ... Количество аргументов должно точно соответствовать значениям, требуемым строкой формата. |
struct.pack_into(format, buffer, offset, v1, v2, ...) | Согласно форматной строкеformatБэйлv1, v2, ... преобразует упакованную строку байтов изoffsetНачальная позиция для записи в доступный для записи буферbuffer. Пожалуйста, обрати вниманиеoffsetЭто обязательный параметр. |
struct.unpack(format, buffer) | Согласно форматной строкеformatиз буфераbufferраспаковать (предположительноpack(format, ...) Бэйл). Возвращаемый результат представляет собой кортеж, даже если он содержит только одну запись. Размер буфера в байтах должен соответствовать размеру, требуемому форматом. |
struct.unpack_from(format, /, buffer, offset=0) | Распаковывает буфер в соответствии с форматом строки формата, начиная со смещения позиции. Результатом является кортеж, даже если он содержит только одну запись. |
struct.iter_unpack(format, buffer) | Согласно форматной строкеformatитеративно из буфераbufferраспаковать. Эта функция возвращает итератор, который будет считывать фрагменты одинакового размера из буфера до тех пор, пока его содержимое не будет исчерпано. |
struct.calcsize(format) | возврат со строкой форматаformatразмер соответствующей структуры (т.е.pack(format, ...) размер результирующего байтового объекта). |
Эти методы в основном предназначены для упаковки и распаковки операций, один из самых важных параметров является формат, который также является форматической строкой, которая указывает формат, который упакован для каждой строки.
Форматировать строку
Строки формата — это механизм, используемый для указания формата данных при упаковке и распаковке данных. Они строятся с использованием символов формата, которые определяют тип упаковываемых/распаковываемых данных. Кроме того, существуют специальные символы, используемые для управления порядком байтов, размером и выравниванием.
порядок байтов, размер и выравнивание
По умолчанию типы C представлены в машинном формате и с порядком байтов, с правильным выравниванием с помощью байтов заполнения, если это необходимо (в соответствии с правилами, используемыми компиляторами C).
Мы также можем вручную указать порядок байтов, размер и выравнивание строки формата:
персонаж | порядок байтов | размер | Выравнивание |
---|---|---|---|
@ |
в необработанных байтах | в необработанных байтах | в необработанных байтах |
= |
в необработанных байтах | стандартный | никто |
< |
прямой порядок байтов | стандартный | никто |
> |
большой порядок байтов | стандартный | никто |
! |
сеть (= обратный порядок байтов) | стандартный | никто |
Big endian и little endian — это два метода хранения данных.
Первый Big Endian хранит старший байт по начальному адресу.
Второй тип Little Endian хранит байт состояния по начальному адресу.
На самом деле, Big Endian больше соответствует привычкам чтения и письма людей, а Little Endian больше соответствует привычкам чтения и письма машин.
Среди двух нынешних основных групп процессоров серия PowerPC использует для хранения данных метод с прямым порядком байтов, а серия x86 использует метод с прямым порядком байтов для хранения данных.
Если различные архитектуры ЦП взаимодействуют напрямую, могут возникнуть проблемы из-за различий в порядке чтения.
Заполнение только автоматически добавляется между непрерывными структурными элементами. Направка не добавляет к началу и конец кодированной структуры.
При использовании неродных размеров байтов и выравниваний, например '', '=' и '!', заполнение не добавляется.
символ формата
Давайте посмотрим, какие форматы имеют символы:
Формат | Тип С | Тип Python | Стандартный размер (байты) |
---|---|---|---|
x |
байты заполнения | никто | |
c |
char |
Строка байтов длины 1 | 1 |
b |
signed char |
целое число | 1 |
B |
unsigned char |
целое число | 1 |
? |
_Bool |
bool | 1 |
h |
short |
целое число | 2 |
H |
unsigned short |
целое число | 2 |
i |
int |
целое число | 4 |
I |
unsigned int |
целое число | 4 |
l |
long |
целое число | 4 |
L |
unsigned long |
целое число | 4 |
q |
long long |
целое число | 8 |
Q |
unsigned long long |
целое число | 8 |
n |
ssize_t |
целое число | |
N |
size_t |
целое число | |
e |
(6) | число с плавающей запятой | 2 |
f |
float |
число с плавающей запятой | 4 |
d |
double |
число с плавающей запятой | 8 |
s |
char[] |
байтовая строка | |
p |
char[] |
байтовая строка | |
P |
void * |
целое число |
номер формата
Например, если мы хотим упаковать объект int, мы можем написать:
In [101]: from struct import *
In [102]: pack('i',10)
Out[102]: b'\n\x00\x00\x00'
In [103]: unpack('i',b'\n\x00\x00\x00')
Out[103]: (10,)
In [105]: calcsize('i')
Out[105]: 4
В приведенном выше примере мы упаковали объект int 10, а затем распаковали его. И длина i вычисляется как 4 байта в этом формате.
Вы можете видеть, что выводb'\n\x00\x00\x00'
, я не буду вдаваться в смысл этого вывода здесь. Буква b в начале представляет собой байт, за которым следует кодировка байта.
Символ формата можно использовать с целым числом повторений. Например, строка формата'4h'
смысл и'hhhh'
Точно так же.
Посмотрите, как упаковать 4 коротких типа:
In [106]: pack('4h',2,3,4,5)
Out[106]: b'\x02\x00\x03\x00\x04\x00\x05\x00'
In [107]: unpack('4h',b'\x02\x00\x03\x00\x04\x00\x05\x00')
Out[107]: (2, 3, 4, 5)
Пробелы между форматами игнорируются, но не должно быть пробелов в символах формата в случае метода struct.calcsize.
При упаковке значений с использованием одного из целочисленных форматов ('b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'q', 'Q ') Когда x , struct.error будет вызвана, если x находится за пределами допустимого диапазона формата.
символ формата
Помимо чисел, чаще всего используются символы и строки.
Давайте сначала посмотрим, как использовать символы форматирования, поскольку длина символа составляет 1 байт, нам нужно сделать это:
In [109]: pack('4c',b'a',b'b',b'c',b'd')
Out[109]: b'abcd'
In [110]: unpack('4c',b'abcd')
Out[110]: (b'a', b'b', b'c', b'd')
In [111]: calcsize('4c')
Out[111]: 4
Буква b перед символом указывает, что это символ, в противном случае он будет рассматриваться как строка.
строка формата
Посмотрите еще раз на формат строки:
In [114]: pack('4s',b'abcd')
Out[114]: b'abcd'
In [115]: unpack('4s',b'abcd')
Out[115]: (b'abcd',)
In [116]: calcsize('4s')
Out[116]: 4
In [117]: calcsize('s')
Out[117]: 1
Вы можете видеть, что для строк calcsize возвращает длину в байтах.
эффект заполнения
Порядок символов формата может влиять на размер, поскольку отступы, необходимые для удовлетворения требований выравнивания, отличаются:
>>> pack('ci', b'*', 0x12131415)
b'*\x00\x00\x00\x12\x13\x14\x15'
>>> pack('ic', 0x12131415, b'*')
b'\x12\x13\x14\x15*'
>>> calcsize('ci')
8
>>> calcsize('ic')
5
В следующем примере мы покажем, как вручную повлиять на эффект заливки:
In [120]: pack('llh',1, 2, 3)
Out[120]: b'\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00'
В вышеприведенном примере мы упаковали 1,2,3 тройки, но формат не тот, а именно длинный, длинный, короткий.
Поскольку четыре байта длинные, короткие 2 байта, они по своей сути не выровнены.
Если мы хотим выровнять, мы можем добавить0l
Представляет 0 long для заполнения вручную:
In [118]: pack('llh0l', 1, 2, 3)
Out[118]: b'\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00'
In [122]: unpack('llh0l',b'\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00')
Out[122]: (1, 2, 3)
сложное приложение
Наконец, рассмотрим сложное приложение, в котором данные непосредственно из распаковки считываются в кортеж:
>>> record = b'raymond \x32\x12\x08\x01\x08'
>>> name, serialnum, school, gradelevel = unpack('<10sHHb', record)
>>> from collections import namedtuple
>>> Student = namedtuple('Student', 'name serialnum school gradelevel')
>>> Student._make(unpack('<10sHHb', record))
Student(name=b'raymond ', serialnum=4658, school=264, gradelevel=8)
Эта статья была включена вWoohoo.freudpress.com/13-Python-is…
Самая популярная интерпретация, самая глубокая галантерея, самые краткие уроки и множество трюков, о которых вы не знаете, ждут вас!
Добро пожаловать, чтобы обратить внимание на мой официальный аккаунт: «Программируйте эти вещи», разбирайтесь в технологиях, лучше поймите себя!