国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

Python如何讀寫二進(jìn)制數(shù)組數(shù)據(jù)

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

問(wèn)題

你想讀寫一個(gè)二進(jìn)制數(shù)組的結(jié)構(gòu)化數(shù)據(jù)到Python元組中。

解決方案

可以使用 struct 模塊處理二進(jìn)制數(shù)據(jù)。 下面是一段示例代碼將一個(gè)Python元組列表寫入一個(gè)二進(jìn)制文件,并使用 struct 將每個(gè)元組編碼為一個(gè)結(jié)構(gòu)體。

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)

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

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 ...

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

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 ...

兩種情況下的結(jié)果都是一個(gè)可返回用來(lái)創(chuàng)建該文件的原始元組的可迭代對(duì)象。

討論

對(duì)于需要編碼和解碼二進(jìn)制數(shù)據(jù)的程序而言,通常會(huì)使用 struct 模塊。 為了聲明一個(gè)新的結(jié)構(gòu)體,只需要像這樣創(chuàng)建一個(gè) Struct 實(shí)例即可:

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

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

產(chǎn)生的 Struct 實(shí)例有很多屬性和方法用來(lái)操作相應(yīng)類型的結(jié)構(gòu)。 size 屬性包含了結(jié)構(gòu)的字節(jié)數(shù),這在I/O操作時(shí)非常有用。 pack() 和 unpack() 方法被用來(lái)打包和解包數(shù)據(jù)。比如:

>>> 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)>>>

有時(shí)候你還會(huì)看到 pack() 和 unpack() 操作以模塊級(jí)別函數(shù)被調(diào)用,類似下面這樣:

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

這樣可以工作,但是感覺(jué)沒(méi)有實(shí)例方法那么優(yōu)雅,特別是在你代碼中同樣的結(jié)構(gòu)出現(xiàn)在多個(gè)地方的時(shí)候。 通過(guò)創(chuàng)建一個(gè) Struct 實(shí)例,格式代碼只會(huì)指定一次并且所有的操作被集中處理。 這樣一來(lái)代碼維護(hù)就變得更加簡(jiǎn)單了(因?yàn)槟阒恍枰淖円惶幋a即可)。

讀取二進(jìn)制結(jié)構(gòu)的代碼要用到一些非常有趣而優(yōu)美的編程技巧。 在函數(shù) read_records 中,iter() 被用來(lái)創(chuàng)建一個(gè)返回固定大小數(shù)據(jù)塊的迭代器。 這個(gè)迭代器會(huì)不斷的調(diào)用一個(gè)用戶提供的可調(diào)用對(duì)象(比如 lambda: f.read(record_struct.size) ), 直到它返回一個(gè)特殊的值(如b’‘),這時(shí)候迭代停止。例如:

>>> 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@’>>>

如你所見,創(chuàng)建一個(gè)可迭代對(duì)象的一個(gè)原因是它能允許使用一個(gè)生成器推導(dǎo)來(lái)創(chuàng)建記錄。 如果你不使用這種技術(shù),那么代碼可能會(huì)像下面這樣:

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)

在函數(shù) unpack_records() 中使用了另外一種方法 unpack_from() 。 unpack_from() 對(duì)于從一個(gè)大型二進(jìn)制數(shù)組中提取二進(jìn)制數(shù)據(jù)非常有用, 因?yàn)樗粫?huì)產(chǎn)生任何的臨時(shí)對(duì)象或者進(jìn)行內(nèi)存復(fù)制操作。 你只需要給它一個(gè)字節(jié)字符串(或數(shù)組)和一個(gè)字節(jié)偏移量,它會(huì)從那個(gè)位置開始直接解包數(shù)據(jù)。

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

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))

這種方案除了代碼看上去很復(fù)雜外,還得做很多額外的工作,因?yàn)樗鼒?zhí)行了大量的偏移量計(jì)算, 復(fù)制數(shù)據(jù)以及構(gòu)造小的切片對(duì)象。 如果你準(zhǔn)備從讀取到的一個(gè)大型字節(jié)字符串中解包大量的結(jié)構(gòu)體的話,unpack_from() 會(huì)表現(xiàn)的更出色。

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

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)

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

>>> 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)>>>

最后提一點(diǎn),如果你需要從已知的文件格式(如圖片格式,圖形文件,HDF5等)中讀取二進(jìn)制數(shù)據(jù)時(shí), 先檢查看看Python是不是已經(jīng)提供了現(xiàn)存的模塊。因?yàn)椴坏饺f(wàn)不得已沒(méi)有必要去重復(fù)造輪子。

以上就是Python如何讀寫二進(jìn)制數(shù)組數(shù)據(jù)的詳細(xì)內(nèi)容,更多關(guān)于Python讀寫二進(jìn)制數(shù)組數(shù)據(jù)的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Python 編程
相關(guān)文章:
主站蜘蛛池模板: 免费国产成人 | 日本免费一区二区三区毛片 | 久草在线视频精品 | 午夜人成| 目韩一区二区三区系列片丶 | 久久亚洲精品中文字幕三区 | 亚洲精品美女在线观看播放 | 在线观看亚洲人成网站 | 色综合久久一本首久久 | 欧美高清性色生活片免费观看 | 狠狠色综合网站久久久久久久 | 一级毛片免费视频网站 | 免费区欧美一级毛片精品 | fc2久久| 欧美国产合集在线视频 | 黄网站免费在线 | 欧美男女网站 | 99久久综合狠狠综合久久一区 | 国产精品_国产精品_国产精品 | 久久99亚洲网美利坚合众国 | 日韩中文字幕视频在线 | 国产男女交性视频播放免费bd | 亚洲三级免费观看 | 中文日韩字幕 | 99久久精品免费国产一区二区三区 | 女人叉开腿让男人捅 | 国产乱码精品一区二区三区卡 | 久久观看视频 | 美女扒开腿让男生桶爽网站 | 精品一区二区影院在线 | 亚洲天堂视频在线免费观看 | 好吊妞国产欧美日韩视频 | avhd101天天看新片 | 国产一国产a一级毛片 | 久久性久久性久久久爽 | 欧美成人精品 | 国产短裙黑色丝袜在线观看下 | 在线精品视频免费观看 | 国产在线精品一区二区三区不卡 | 免费看黄网 | 草久在线观看 |