电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

Python如何讀寫二進制數組數據

瀏覽:4日期:2022-07-15 14:10:14

問題

你想讀寫一個二進制數組的結構化數據到Python元組中。

解決方案

可以使用 struct 模塊處理二進制數據。 下面是一段示例代碼將一個Python元組列表寫入一個二進制文件,并使用 struct 將每個元組編碼為一個結構體。

from struct import Structdef write_records(records, format, f): ’’’ Write a sequence of tuples to a binary file of structures. ’’’ record_struct = Struct(format) for r in records: f.write(record_struct.pack(*r))# Exampleif __name__ == ’__main__’: records = [ (1, 2.3, 4.5),(6, 7.8, 9.0),(12, 13.4, 56.7) ] with open(’data.b’, ’wb’) as f: write_records(records, ’<idd’, f)

有很多種方法來讀取這個文件并返回一個元組列表。 首先,如果你打算以塊的形式增量讀取文件,你可以這樣做:

from struct import Structdef read_records(format, f): record_struct = Struct(format) chunks = iter(lambda: f.read(record_struct.size), b’’) return (record_struct.unpack(chunk) for chunk in chunks)# Exampleif __name__ == ’__main__’: with open(’data.b’,’rb’) as f: for rec in read_records(’<idd’, f): # Process rec ...

如果你想將整個文件一次性讀取到一個字節字符串中,然后在分片解析。那么你可以這樣做:

from struct import Structdef unpack_records(format, data): record_struct = Struct(format) return (record_struct.unpack_from(data, offset) for offset in range(0, len(data), record_struct.size))# Exampleif __name__ == ’__main__’: with open(’data.b’, ’rb’) as f: data = f.read() for rec in unpack_records(’<idd’, data): # Process rec ...

兩種情況下的結果都是一個可返回用來創建該文件的原始元組的可迭代對象。

討論

對于需要編碼和解碼二進制數據的程序而言,通常會使用 struct 模塊。 為了聲明一個新的結構體,只需要像這樣創建一個 Struct 實例即可:

# Little endian 32-bit integer, two double precision floatsrecord_struct = Struct(’<idd’)

結構體通常會使用一些結構碼值i, d, f等 [參考 Python文檔 ]。 這些代碼分別代表某個特定的二進制數據類型如32位整數,64位浮點數,32位浮點數等。 第一個字符 < 指定了字節順序。在這個例子中,它表示”低位在前”。 更改這個字符為 > 表示高位在前,或者是 ! 表示網絡字節順序。

產生的 Struct 實例有很多屬性和方法用來操作相應類型的結構。 size 屬性包含了結構的字節數,這在I/O操作時非常有用。 pack() 和 unpack() 方法被用來打包和解包數據。比如:

>>> from struct import Struct>>> record_struct = Struct(’<idd’)>>> record_struct.size20>>> record_struct.pack(1, 2.0, 3.0)b’x01x00x00x00x00x00x00x00x00x00x00@x00x00x00x00x00x00x08@’>>> record_struct.unpack(_)(1, 2.0, 3.0)>>>

有時候你還會看到 pack() 和 unpack() 操作以模塊級別函數被調用,類似下面這樣:

>>> import struct>>> struct.pack(’<idd’, 1, 2.0, 3.0)b’x01x00x00x00x00x00x00x00x00x00x00@x00x00x00x00x00x00x08@’>>> struct.unpack(’<idd’, _)(1, 2.0, 3.0)>>>

這樣可以工作,但是感覺沒有實例方法那么優雅,特別是在你代碼中同樣的結構出現在多個地方的時候。 通過創建一個 Struct 實例,格式代碼只會指定一次并且所有的操作被集中處理。 這樣一來代碼維護就變得更加簡單了(因為你只需要改變一處代碼即可)。

讀取二進制結構的代碼要用到一些非常有趣而優美的編程技巧。 在函數 read_records 中,iter() 被用來創建一個返回固定大小數據塊的迭代器。 這個迭代器會不斷的調用一個用戶提供的可調用對象(比如 lambda: f.read(record_struct.size) ), 直到它返回一個特殊的值(如b’‘),這時候迭代停止。例如:

>>> f = open(’data.b’, ’rb’)>>> chunks = iter(lambda: f.read(20), b’’)>>> chunks<callable_iterator object at 0x10069e6d0>>>> for chk in chunks:... print(chk)...b’x01x00x00x00ffffffx02@x00x00x00x00x00x00x12@’b’x06x00x00x00333333x1f@x00x00x00x00x00x00'@’b’x0cx00x00x00xcdxccxccxccxccxcc*@x9ax99x99x99x99YL@’>>>

如你所見,創建一個可迭代對象的一個原因是它能允許使用一個生成器推導來創建記錄。 如果你不使用這種技術,那么代碼可能會像下面這樣:

def read_records(format, f): record_struct = Struct(format) while True: chk = f.read(record_struct.size) if chk == b’’: break yield record_struct.unpack(chk)

在函數 unpack_records() 中使用了另外一種方法 unpack_from() 。 unpack_from() 對于從一個大型二進制數組中提取二進制數據非常有用, 因為它不會產生任何的臨時對象或者進行內存復制操作。 你只需要給它一個字節字符串(或數組)和一個字節偏移量,它會從那個位置開始直接解包數據。

如果你使用 unpack() 來代替 unpack_from() , 你需要修改代碼來構造大量的小的切片以及進行偏移量的計算。比如:

def unpack_records(format, data): record_struct = Struct(format) return (record_struct.unpack(data[offset:offset + record_struct.size]) for offset in range(0, len(data), record_struct.size))

這種方案除了代碼看上去很復雜外,還得做很多額外的工作,因為它執行了大量的偏移量計算, 復制數據以及構造小的切片對象。 如果你準備從讀取到的一個大型字節字符串中解包大量的結構體的話,unpack_from() 會表現的更出色。

在解包的時候,collections 模塊中的命名元組對象或許是你想要用到的。 它可以讓你給返回元組設置屬性名稱。例如:

from collections import namedtupleRecord = namedtuple(’Record’, [’kind’,’x’,’y’])with open(’data.p’, ’rb’) as f: records = (Record(*r) for r in read_records(’<idd’, f))for r in records: print(r.kind, r.x, r.y)

如果你的程序需要處理大量的二進制數據,你最好使用 numpy 模塊。 例如,你可以將一個二進制數據讀取到一個結構化數組中而不是一個元組列表中。就像下面這樣:

>>> import numpy as np>>> f = open(’data.b’, ’rb’)>>> records = np.fromfile(f, dtype=’<i,<d,<d’)>>> recordsarray([(1, 2.3, 4.5), (6, 7.8, 9.0), (12, 13.4, 56.7)],dtype=[(’f0’, ’<i4’), (’f1’, ’<f8’), (’f2’, ’<f8’)])>>> records[0](1, 2.3, 4.5)>>> records[1](6, 7.8, 9.0)>>>

最后提一點,如果你需要從已知的文件格式(如圖片格式,圖形文件,HDF5等)中讀取二進制數據時, 先檢查看看Python是不是已經提供了現存的模塊。因為不到萬不得已沒有必要去重復造輪子。

以上就是Python如何讀寫二進制數組數據的詳細內容,更多關于Python讀寫二進制數組數據的資料請關注好吧啦網其它相關文章!

標簽: Python 編程
相關文章:
主站蜘蛛池模板: 协议书_协议合同格式模板范本大全| 检验科改造施工_DSA手术室净化_导管室装修_成都特殊科室建设厂家_医疗净化工程公司_四川华锐 | 广州/东莞小字符喷码机-热转印打码机-喷码机厂家-广州瑞润科技 | 杭州用友|用友软件|用友财务软件|用友ERP系统--杭州协友软件官网 | 广州冷却塔维修厂家_冷却塔修理_凉水塔风机电机填料抢修-广东康明节能空调有限公司 | 安徽净化板_合肥岩棉板厂家_玻镁板厂家_安徽科艺美洁净科技有限公司 | 安全光栅|射频导纳物位开关|音叉料位计|雷达液位计|两级跑偏开关|双向拉绳开关-山东卓信机械有限公司 | 粉丝机械,粉丝烘干机,粉丝生产线-招远市远东粉丝机械有限公司 | 行星齿轮减速机,减速机厂家,山东减速机-淄博兴江机械制造 | 恒温振荡混匀器-微孔板振荡器厂家-多管涡旋混匀器厂家-合肥艾本森(www.17world.net) | 点胶机_点胶阀_自动点胶机_智能点胶机_喷胶机_点胶机厂家【欧力克斯】 | 尊享蟹太太美味,大闸蟹礼卡|礼券|礼盒在线预订-蟹太太官网 | 干式变压器厂_干式变压器厂家_scb11/scb13/scb10/scb14/scb18干式变压器生产厂家-山东科锐变压器有限公司 | 冷水机,风冷冷水机,水冷冷水机,螺杆冷水机专业制造商-上海祝松机械有限公司 | 不干胶标签-不干胶贴纸-不干胶标签定制-不干胶标签印刷厂-弗雷曼纸业(苏州)有限公司 | 篷房[仓储-婚庆-展览-活动]生产厂家-江苏正德装配式帐篷有限公司 | 无锡网站建设_企业网站定制-网站制作公司-阿凡达网络 | 冷镦机-多工位冷镦机-高速冷镦机厂家-温州金诺机械设备制造有限公司 | 菏泽知彼网络科技有限公司| 传动滚筒_厂家-淄博海恒机械制造厂 | 耐高温风管_耐高温软管_食品级软管_吸尘管_钢丝软管_卫生级软管_塑料波纹管-东莞市鑫翔宇软管有限公司 | 便携式XPDM露点仪-在线式防爆露点仪-增强型烟气分析仪-约克仪器 冰雕-冰雪世界-大型冰雕展制作公司-赛北冰雕官网 | 直读光谱仪,光谱分析仪,手持式光谱仪,碳硫分析仪,创想仪器官网 | 起好名字_取个好名字_好名网免费取好名在线打分 | 顺辉瓷砖-大国品牌-中国顺辉 | LED投光灯-工矿灯-led路灯头-工业灯具 - 山东普瑞斯照明科技有限公司 | 杭州成人高考_浙江省成人高考网上报名 | 齿轮减速机_齿轮减速电机-VEMT蜗轮蜗杆减速机马达生产厂家瓦玛特传动瑞环机电 | 磷酸肌酸二钠盐,肌酐磷酰氯-沾化欣瑞康生物科技 | 沈阳激光机-沈阳喷码机-沈阳光纤激光打标机-沈阳co2激光打标机 | 数码听觉统合训练系统-儿童感觉-早期言语评估与训练系统-北京鑫泰盛世科技发展有限公司 | 砂石生产线_石料生产线设备_制砂生产线设备价格_生产厂家-河南中誉鼎力智能装备有限公司 | 污水/卧式/潜水/钻井/矿用/大型/小型/泥浆泵,价格,参数,型号,厂家 - 安平县鼎千泵业制造厂 | 灌木树苗-绿化苗木-常绿乔木-价格/批发/基地 - 四川成都途美园林 | 管形母线,全绝缘铜管母线厂家-山东佰特电气科技有限公司 | 精密模具加工制造 - 富东懿 | 杭州翻译公司_驾照翻译_专业人工翻译-杭州以琳翻译有限公司官网 组织研磨机-高通量组织研磨仪-实验室多样品组织研磨机-东方天净 | 置顶式搅拌器-优莱博化学防爆冰箱-磁驱搅拌器-天津市布鲁克科技有限公司 | 喷涂流水线,涂装流水线,喷漆流水线-山东天意设备科技有限公司 | 谈股票-今日股票行情走势分析-牛股推荐排行榜 | 冷油器-冷油器换管改造-连云港灵动列管式冷油器生产厂家 |