bytes 與 string 之間互轉
Python3 最重要的新特性大概要算是對文本和二進制數據作了更為清晰的區分。文本總是 Unicode,由str類型表示,二進制數據則由 bytes 類型表示。Python3 不會以任意隱式的方式混用 str 和 bytes,正是這使得兩者的區分特別清晰。不能拼接字符串和字節包,也無法在字節包里搜索字符串(反之亦然),也不能將字符串傳入參數為字節包的函數(反之亦然)
b1=b'sdf' s1='sag' print(type(b1),type(s1))#<class 'bytes'> <class 'str'> # bytes按utf8的方式解碼成str b2=b1.decode('utf8') # str按utf8的方式編碼成bytes s2=s1.encode('utf8')
base64 轉碼
import base64 with open("img.png", "rb") as f: # b64encode是編碼,b64decode是解碼 base64_data = base64.b64encode(f.read()) print(base64_data) r = base64.b64decode(base64_data) print(type(r), r) f.close()
bytes 轉成 numpy array
import cv2 import numpy as np b = b'aaaaaaaaa' # bytes image_array1 = np.frombuffer(b, dtype=np.uint8) # numpy array img_decode = cv2.imdecode(image_array1, 1) # 效果等同於cv2.imread()
BytesIO 和 StringIO
Python3 中 BytesIO 和 StringIO 最大的優勢就是可以將讀寫的操作在內存中進行,相對於磁盤級別的 IO 既省了時間也省了出錯的概率
StringIO
from io import StringIO f = StringIO() f.write('hello') # 內存級別寫入操作 print(f.getvalue()) # 得到文件內容(相當於磁盤IO操作的read()) # 也可以用一個str初始化StringIO,然后,像讀文件一樣讀取: from io import StringIO f = StringIO('Hello!\nHi!\nGoodbye!') while True: s = f.readline() if s == '': break print(s.strip()) ''' Hello! Hi! Goodbye! '''
BytesIO
StringIO操作的只能是str,如果要操作二進制數據,就需要使用BytesIO,BytesIO實現了在內存中讀寫bytes
from io import BytesIO f = BytesIO() f.write('中文'.encode('utf-8')) print(f.getvalue()) # b'\xe4\xb8\xad\xe6\x96\x87' # 寫入的不是str,而是經過UTF-8編碼的bytes。 # 和StringIO類似,可以用一個bytes初始化BytesIO,然后,像讀文件一樣讀取: from io import BytesIO f = BytesIO(b'\xe4\xb8\xad\xe6\x96\x87') f.read() # b'\xe4\xb8\xad\xe6\x96\x87'
注意指針問題
.getvalue() 可以查看整個輸入后的情況 .write() 的初始位置是 0,輸入多少后到多少位,直接構造之后初始位置不變還是0 .seek() 是直接去某個 position .tell()可以查看當前位置 .read()讀取完指針位置自動到末尾
f=StringIO('abc') f.read() #返回'abc' f.read() #返回'' 因為使用過一次read之后指針會發生移動 f.getvalue() #返回'abc' 因為getvalue不受指針影響 f=StringIO('') f.write('abc') f.read() #返回'' 因為write已經使指針發生了移動 f.getvalue() #返回'abc' 因為getvalue不受指針影響 f.seek(0) #解決方法:用seek將指針歸零 f.read() #返回'abc'
BufferedReader
BufferedReader 可以將 postman 傳遞的 Filestorage 類型的數據轉換成 BufferedReader 類型,之后就可以轉換成 numpy array,進行 cv2 的操作
from io import BufferedReader img = request.file.get('xxx') # 假設postman傳了圖片到服務端,服務端接收到后為img # 轉成BufferedReader格式 img_buff = BufferedReader(img) # 得到byte數據 img_byte = BufferedReader.read(img_buff ) # 轉成numpy數組 nparr = np.frombuffer(img_byte , dtype=np.uint8) # 轉成cv2.imread相同效果的數據 img_decode = cv2.imdecode(nparr, 1) print(img_decode.shape)