亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Python如何利用struct進行二進制文件或數(shù)據(jù)流

 更新時間:2024年01月20日 10:49:29   作者:Wei.Studio  
這篇文章主要介紹了Python如何利用struct進行二進制文件或數(shù)據(jù)流問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

利用struct進行二進制文件或數(shù)據(jù)流操作

在實際工作場景中,特別是在嵌入式開發(fā)過程中,經(jīng)常需要和二進制操作打交道。

這里舉兩個典型例子:

設(shè)備上的一些配置參數(shù)通常是以二進制的形式保存在Flash等非易失存儲芯片中,而配置參數(shù)的格式與內(nèi)容編輯工作通常是在PC上中完成,將生成的xxx.bin文件下載到設(shè)備并寫入Flash中,設(shè)備啟動后從Flash固定地址讀取配置到內(nèi)存中使用。如果能夠在PC上以某種腳本的形式方便的對二進制文件的格式和內(nèi)容進行編輯,或者將二進制文件解析為方便閱讀的格式,可以提升很多工作效率,使用起來也非常方便

設(shè)備和管理端(上位機、服務(wù)器等)需要通過一定的接口進行數(shù)據(jù)交互,操作人員通過管理端訪問和控制設(shè)備,例如使用UART進行串口通信,或者使用Ethernet接口進行UDP/TCP甚至應(yīng)用層協(xié)議通信。無論使用什么接口,都需要對業(yè)務(wù)數(shù)據(jù)進行協(xié)議封裝,使用二進制的數(shù)據(jù)流封裝是一個非常普遍的選擇,尤其是在資源非常緊張的嵌入式平臺上,與使用字符串或JSON格式傳輸數(shù)據(jù)的協(xié)議(例如HTTP)相比,二進制占用的帶寬和內(nèi)存資源較少。另外,很多嵌入式平臺上由于資源限制(內(nèi)存、庫函數(shù)支持等),并不能很好的集成復(fù)雜協(xié)議的很多要求,反而是二進制格式是C語言原生支持,也更方便移植

Python作為一個靈活的腳本語言,在運行環(huán)境搭建、編碼和調(diào)試方面都很便利,而且有豐富的第三方庫支持,通常只需要很少量的代碼就能夠輕松完成很多工作。

以下內(nèi)容分別從二進制文件和二進制數(shù)據(jù)流方面對Python中struct的用法進行說明

struct進行二進制操作的用法

struct是Python內(nèi)置的一個模塊,struct對數(shù)據(jù)格式的封裝能夠與C語言進行非常方便的適配,能夠完美的支持C語言原生的數(shù)據(jù)類型,以及指定字節(jié)順序。

以下表格是struct封裝格式與C語言數(shù)據(jù)類型的對應(yīng)關(guān)系

struct支持的格式
FormatC TypePython TypeSize
xpad byteno value1
ccharstring of length 11
bsigned charinteger1
Bunsigned charinteger1
?_Boolbool1
hshortinteger2
Hunsigned shortinteger2
iintinteger4
Iunsigned intinteger4
llonginteger4
Lunsigned longinteger4
qlong long integer8
Qunsigned long longinteger8
ffloatfloat4
ddoublefloat8
schar[]string
pchar[]string
pvoid *integer

struct支持指定字節(jié)序,也是通過參數(shù)的方式指定的

struct字節(jié)序定義
CodeMeaning
@Native order
=Native standard
<Little-endian
>Big-endian
!Network order

怎么用?

struct提供了一些函數(shù)來封裝數(shù)據(jù)

  • pack(fmt, v1, v2, ...):按照給定的格式fmt,將數(shù)據(jù)v1和v2封裝
  • rdata = unpack(fmt, data):按照給定的格式fmt,將源數(shù)據(jù)data解析為元組形式的rdata
  • calcsize(fmt):計算給定格式占用的內(nèi)存字節(jié)數(shù)
  • pack_into(fmt, buffer, offset, v1, v2…):按照給定的格式fmt將數(shù)據(jù)以追加的方式封裝,寫入以offset開始的buffer中
  • rdata = unpack_from(fmt, buffer, offset):按照給定的格式fmt解析以offset開始的緩沖區(qū)buffer,并返回解析結(jié)果

這些函數(shù)接口中的"fmt",是字符串的形式,其內(nèi)容就是上文中兩個表格的第一列。

例如:以下代碼將16進制字"0x1516"分別以小端和大端形式封裝為x1和x2

import struct
 
x1 = struct.pack('H', 0x1516)
x2 = struct.pack('>H', 0x1516)
print('x1:{} x2:{}'.format(x1, x2))
 
# running result:
# x1:b'\x15\x13' x2:b'\x13\x15'

參數(shù)中的"fmt"可以是單獨某一種格式,也可以是多種格式的混合

例如:以下代碼將一個十六進制字節(jié)"0xaa"和雙字"0x11223344"合并封裝為x,然后再解析為

import struct
 
x = struct.pack('BI', 0xaa, 0x11223344)
d1, d2 = struct.unpack('BI', x)
print('pack:{} unpack:{:#x} {:#x}'.format(x, d1, d2))
 
# running result:
# pack:b'\xaa\x00\x00\x00D3"\x11' unpack:0xaa 0x11223344

二進制文件操作

利用struct進行二進制文件編輯,有以下關(guān)鍵點

  • 使用ctypes.create_string_buffer創(chuàng)建buffer
  • 使用pack_into進行追加封裝
  • 文件打開使用'b'標(biāo)志表示以二進制方式寫入

以下例子利用struct封裝一個固定格式的數(shù)據(jù)到bin文件,并讀出解析

# python3.7.6
 
import struct
from ctypes import create_string_buffer
 
 
"""
Python struct example
    package a format into binary finle
    
    format define:
    31               15              0
    +--------------------------------+
    |              mark              |
    +----------------+---------------+
    |     version    |    length     |
    +----------------+---------------+
    |            checksum            |
    +--------------------------------+
    |              data...           |
    +--------------------------------+
"""
 
 
def dump(mark, version, length, data, checksum):
    print('\n---- dump ----')
    print('mark:{:#X}'.format(mark))
    print('version:{}.{}'.format(version['major'], version['minor']))
    print('data length:{}'.format(length))
    print('checksum:{}'.format(checksum))
    print('data:{}'.format(data))
    print('--------------\n')
 
 
def save_bin(binary_file='test.bin', mark=0x5A5A5A5A, version={'major':1, 'minor':0}):
    
    offset = 0
    checksum = 0
    dataLength = 0
    data = [1,2,3,4,5,6,7,8]
    
    # create buffer
    buffer_size = 4+2+2+4+len(data)*4
    buffer = create_string_buffer(buffer_size)
    print('create buffer with {}byte'.format(buffer_size))
 
    # pack mark+version+length
    fmt = 'IBBH'
    dataLength = len(data)
    struct.pack_into(fmt, buffer, offset, mark, version['major'], version['minor'], dataLength)
    offset = offset + struct.calcsize(fmt)
 
    # pack data
    fmt = 'I'
    offset = offset + 4     # skip checksum
    for x in data:
        struct.pack_into(fmt, buffer, offset, x)
        offset = offset + struct.calcsize(fmt)
 
    # pack checksum
    fmt = 'I'
    offset = 8
    for x in buffer:
        d = x[0]
        checksum = checksum + d
    struct.pack_into(fmt, buffer, offset, checksum)
 
    # write to file
    f = open(binary_file, 'wb')
    f.write(buffer)
    f.close()
 
    dump(mark, version, dataLength, data, checksum)
 
    print('{}byte write to {}'.format(len(buffer), binary_file))
 
def read_bin(binary_file='test.bin'):
 
    offset = 0
    data = []
 
    # open and read file
    fmt = 'IBBHI'
    f = open(binary_file, 'rb')
    buffer = f.read()
    mark, major, minor, length, checksum = struct.unpack_from(fmt, buffer, 0)
    version = {'major':major, 'minor':minor}
 
    offset = struct.calcsize(fmt)
    for i in range(length-1):
        offset = offset + 4
        d = struct.unpack_from('I', buffer, offset)
        data.append(d[0])
 
    dump(mark, version, length, data, checksum)
    print('read {}byte from {}'.format(len(buffer), binary_file))
 
 
save_bin()
read_bin()
 
 
"""
running result:
create buffer with 44byte
---- dump ----
mark:0X5A5A5A5A
version:1.0
data length:8
checksum:405
data:[1, 2, 3, 4, 5, 6, 7, 8]
--------------
44byte write to test.bin
---- dump ----
mark:0X5A5A5A5A
version:1.0
data length:8
checksum:405
data:[2, 3, 4, 5, 6, 7, 8]
--------------
read 44byte from test.bin
"""

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Python 實現(xiàn)使用dict 創(chuàng)建二維數(shù)據(jù)、DataFrame

    Python 實現(xiàn)使用dict 創(chuàng)建二維數(shù)據(jù)、DataFrame

    下面小編就為大家分享一篇Python 實現(xiàn)使用dict 創(chuàng)建二維數(shù)據(jù)、DataFrame,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-04-04
  • Python中使用支持向量機SVM實踐

    Python中使用支持向量機SVM實踐

    這篇文章主要為大家詳細(xì)介紹了Python中使用支持向量機SVM實踐,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • python Dataframe字符串合并的操作方法

    python Dataframe字符串合并的操作方法

    Dataframe的字符串合并包括2種場景,1.合并df中其中幾列字符串;2.將df中的字符串與外部字符串合并,本文主要介紹在Python下對Dataframe進行字符串合并操作的方法,感興趣的朋友跟隨小編一起看看吧
    2024-06-06
  • Python快速優(yōu)雅的批量修改Word文檔樣式

    Python快速優(yōu)雅的批量修改Word文檔樣式

    本文主要將涉及os,glob,docx模塊的綜合應(yīng)用,幫助大家快速批量修改Word文檔樣式實現(xiàn)辦公自動化,感興趣的朋友可以了解下
    2021-05-05
  • pygame實現(xiàn)貪吃蛇游戲

    pygame實現(xiàn)貪吃蛇游戲

    這篇文章主要為大家詳細(xì)介紹了pygame實現(xiàn)貪吃蛇游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • 利用Python的Django框架中的ORM建立查詢API

    利用Python的Django框架中的ORM建立查詢API

    這篇文章主要介紹了利用Python的Django框架中的ORM建立查詢API,對Managers和QuerySets進行了著重介紹,需要的朋友可以參考下
    2015-04-04
  • Windows直接運行python程序的兩種方法

    Windows直接運行python程序的兩種方法

    本文主要介紹了Windows直接運行python程序,包括新建bat腳本和新建vbs腳本,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-03-03
  • PyQt子線程處理業(yè)務(wù)事件的問題解決

    PyQt子線程處理業(yè)務(wù)事件的問題解決

    在PyQt中,主線程通常是指GUI主循環(huán)所在的線程,而子線程則是執(zhí)行實際工作的線程,本文主要介紹了PyQt子線程處理業(yè)務(wù)事件的問題解決,具有一定的參考價值,感興趣的可以了解一下
    2024-02-02
  • Python Pandas pandas.read_sql_query函數(shù)實例用法分析

    Python Pandas pandas.read_sql_query函數(shù)實例用法分析

    在本篇文章里小編給大家整理的是一篇關(guān)于Python Pandas pandas.read_sql_query函數(shù)實例用法分析內(nèi)容,有興趣的朋友們可以跟著學(xué)習(xí)下。
    2021-06-06
  • Python Socket使用實例

    Python Socket使用實例

    這篇文章主要介紹了Python Socket使用實例,具有一定借鑒價值,需要的朋友可以參考下。
    2017-12-12

最新評論