亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么在python中使用struct模塊對字節型數據進行處理

發布時間:2021-03-18 15:45:16 來源:億速云 閱讀:350 作者:Leah 欄目:開發技術

怎么在python中使用struct模塊對字節型數據進行處理?針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

字節順序

一個數據有多個字節表示的時候,字節的順序不同也就決定了值,在struct中有以下幾種字節順序:

字符字節順序尺寸對齊方式
@本機本機本機
=本機標準
<小端標準
>大端標準
網絡標準

對于字節順序,只有大端和小端兩種方式,只是比如你用@和=代表你用本機的字節順序,!代表你使用網絡的字節順序。你不指定字節順序則默認的是@。

本地字節順序是大端或小端,取決于主機系統。例如,Intel x86和AMD64(x86-64)是小端的; 摩托羅拉68000和PowerPC G5是大端; ARM和Intel Itanium具有可切換的字節序(雙字節序)。使用sys.byteorder來檢查你的系統的字節順序。

數據格式

struct支持的打包解包的數據格式如下,我們需要指定格式才能對應處理,其中對應尺寸已列出(以字節為單位):

字符C類型python類型標準尺寸
x填充字節沒有意義的值
cchar長度為1的字節1
bsigned char整型1
Bunsigned char整型1
_Bool布爾1
hshort整型2
Hunsigned short整型2
iint整型4
Iunsigned int整型4
llong整型4
Lunsigned long整型4
qlong long整型8
Qunsigned long long整型8
nssize_t整型
Nsize_t整型
e
浮動2
ffloat浮動4
ddouble浮動8
schar[]字節
pchar[]字節
Pvoid *整型

打包

通過struct的pack(fmt, *args)來實現對各種數據的打包(轉換為對應字節數據),pack的需要傳遞的參數fmt就是數據的格式,包括了字節順序、數據類型;后面的*args參數是需要打包的數據。

vaa = struct.pack('>I', 1255) # vaa: '\x00\x00\x04\xe7' 1*4=1個字節 vab = struct.pack('>II', 1255, 23) # vab: '\x00\x00\x04\xe7\x00\x00\x00\x17' 2*4=8個字節 vac = struct.pack('>2I?', 1255, 23, True) # vac: '\x00\x00\x04\xe7\x00\x00\x00\x17\x01' 2*4+1=9個字節

我們看上述三個使用例子(數據與數據之間沒有填充,都是連續的,比如對于vac我們不知道 它是由兩個4字節無符號整型和一個布爾構成,我們就無法取得正確的值),看fmt參數:

‘>I'代表了以大端的字節順序打包一個4字節無符號整型數據,所以后面只跟了一個無符號整型參數1255;

‘>II'代表了以大端的字節順序打包兩個4字節無符號整型數據,所以后面跟了兩個個無符號整型參數1255和23;

‘>2I?'代表了以大端的字節順序打包兩個4字節無符號整型和一個布爾型數據,所以后面跟了兩個個無符號整型參數1255、23和一個布爾值True。

注意'2I'和'II','4I'和'IIII','2?'和'??'是一樣的效果。

解包

通過struct的unpack(fmt, string)來實現對字符串的解包,fmt和打包的是完全一樣的,如下(返回的結果是一個元組):

vaa = struct.pack('>I', 1255) # vaa: '\x00\x00\x04\xe7'
vab = struct.pack('>II', 1255, 23) # vab: '\x00\x00\x04\xe7\x00\x00\x00\x17'
vaaa = struct.unpack('>I', vaa) # vaaa: <class 'tuple'>: (1255, )
vaba = struct.unpack('>II', vab) # vaba: <class 'tuple'>: (1255, 23)

進階使用

pack_into(fmt, buffer, offset, *args)

fmt參數和pack是一樣的,buffer參數是可寫的緩存區,offset是寫入位置的偏移量,*args是需要寫入的數據。這個有什么用呢,我們想想這樣兩個情況,我們有兩個類型已經打包好,我們想在這兩個已經打包好的數據后面再添加一個數據打包;或者我們要打包的數據很多,我們不可能在pack中把所有需要打包的數據都通過參數傳遞給pack,那你的pack函數可能得寫成千上完個參數了。這時候我們就可以用到這個函數了。

要使用它必須要一個可以寫入的緩存區,我們可以導入一個字符緩存區包,然后創建一個固定大小的緩存區(以字節為單位):

import struct
from ctypes import create_string_buffer

# 創建一個9字節大小的緩存區,初始化默認全部為\x00 
buf = create_string_buffer(9) # buf.raw: '\x00\x00\x00\x00\x00\x00\x00\x00\x00'

# 沖緩存區buf的第0個字節開始打包兩個4字節無符號整型數據1和2
struct.pack_into(">II", buf, 0, 1, 2) # buf.raw: '\x00\x00\x00\x01\x00\x00\x00\x02\x00'
# 然后我們想再打包一個布爾型數據到buf中就可以改變以下偏移量
struct.pack_into(">?", buf, 8, True) # buf.raw: '\x00\x00\x00\x01\x00\x00\x00\x02\x01'

unpack_from(fmt, buffer, offset)和calcsize(fmt)結合解包數據

calcsize用于計算格式字符串所對應的結果的長度,如:struct.calcsize(‘II'),返回8。因為兩個無符號整型所占用的長度是8個字節。unpack_from(fmt, buffer, offset)用于從buffer緩存區中使用fmt格式從offset偏移量處開始解包fmt里對應數量的數據。

import struct
from ctypes import create_string_buffer

buf = create_string_buffer(9)
struct.pack_into(">II", buf, 0, 1, 2)
struct.pack_into(">?", buf, 8, True)
# 記錄位置
pos = 0
# 從buf緩存區中以大端方式從偏移位置pos處解包兩個無符號整型數據返回,注意
#返回值如果只寫一個則返回一個元組,否則你解包幾個數據就要寫幾個返回值。
val = struct.unpack_from('>II', buf, pos) # val: <class 'tuple'>: (1, 2)
val_a, val_b = struct.unpack_from('>II', buf, pos) # val_a: 1 val_b: 2

# 重置解包位置
pos += struct.calcsize('>II') # pos: 8
val_c, = struct.unpack_from('>?', buf, pos) # val_c: True

示例

這個示例是基于mnist手寫數字識別的,我們剛開始有60000張手寫數字的圖片(.bmp格式的),我們通過下述代碼將60000張圖片轉換成字節型數據,bytes.py代碼如下:

import struct
import os
import numpy as np
from ctypes import create_string_buffer
import cv2

# 創建一個60000 * 784 * 1 + 3 * 4字節大小的緩存區,初始化默認全部為\x00
buffer = create_string_buffer(60000 * 784 * 1 + 3 * 4)
def writeBytesData():
 index = 0
 BMP_NUM = 0
 BMP_WIDTH = 28
 BMP_HEIGHT = 28

 # 先保留三個無符號整型的緩存區
 index += struct.calcsize('>III')
 path = 'data/bmp'
 if not os.path.exists(path):
  print('No this dir!')
  return
 list = os.listdir(path)
 for line_bmp in list:
  bmp_path = os.path.join(path, line_bmp)
  if os.path.isdir(bmp_path):
   print('This is not a .bmp')
  else:
   BMP_NUM += 1
   print(BMP_NUM)
   buf = cv2.imread(bmp_path, cv2.IMREAD_GRAYSCALE)
   buf = np.reshape(buf, [784])
   for pos in range(buf.__len__()):
    struct.pack_into('>B', buffer, index, buf[pos])
    index += struct.calcsize('>B')

 # 將保留緩存區的內容填上
 struct.pack_into('>III', buffer, 0, BMP_NUM, BMP_WIDTH, BMP_HEIGHT)
 with open('data/bytes/bytes.bytes', 'wb') as fp:
  fp.write(buffer)


def readFromBytes():
 index = 0
 images = []
 with open('data/bytes/bytes.bytes', 'rb') as fp:
  buffer = fp.read()
  # 解包前三個無符號整型
  bmp_num, bmp_width, bmp_height = struct.unpack_from('>III', buffer, index)

  # 重定位偏移量
  index += struct.calcsize('>III')
  for pos in range(bmp_num):
   img = struct.unpack_from('>784B', buffer, index)
   index += struct.calcsize('>784B')
   # 修改為原來的圖片形狀
   img = np.array(img, dtype=np.uint8)
   img = np.reshape(img, [bmp_height, bmp_width])
   # 顯示圖片
   cv2.imshow('bmp', img)
   # 按任意鍵繼續
   cv2.waitKey(0)
   images.append(img)
 return images


writeBytesData()
readFromBytes()

在寫入bytes文件的時候有點慢,由于有60000張圖片每張要寫28 * 28個字節,其中目錄結構如下,需要圖片的可以去我的下載區下載mnist圖片數據集:

bytes.py
data
 bmp
  1.bmp
  2.bmp
  ...
  60000.bmp
 bytes

關于怎么在python中使用struct模塊對字節型數據進行處理問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

商河县| 贵溪市| 长白| 香港| 德兴市| 运城市| 罗定市| 鹰潭市| 白沙| 梨树县| 珠海市| 莒南县| 门源| 府谷县| 介休市| 盐边县| 富蕴县| 衡水市| 广德县| 茌平县| 弥勒县| 盐津县| 万源市| 北碚区| 泰安市| 宁国市| 门头沟区| 长春市| 深泽县| 中卫市| 嘉禾县| 麻城市| 平遥县| 民勤县| 永康市| 汽车| 丹江口市| 六安市| 尼玛县| 明水县| 开平市|