[英]Binary data gets written as string literal - how to convert it back to bytes?
我正在將壓縮數據作為bytes
類型寫入黑盒 API(即我無法更改引擎蓋下發生的事情)。 當我取回該數據時,它作為string
類型返回,我無法使用通用 python 模塊(zlib、bz2 等)解壓縮該類型
更詳細地說,部分問題在於該字符串包含前導'b'
,例如b'x\\x9c\\xabV*HL\\xd1\\xcd\\xccK\\xcbW\\xb2RPJ\\xcb\\xcfOJ,R\\xaa\\x05\\x00T\\x83\\x07b'
(這是一個字符串類型)。
當我將其與原始二進制表示進行比較時,在引號和前導 B 之外,它是相同的。
如果我嘗試簡單地轉換回字節(例如使用bytes
函數),它會包裝整個內容並轉義斜杠,我得到如下內容:
b"b'x\\\\x9c\\\\xabV*HL\\\\xd1\\\\xcd\\\\xccK\\\\xcbW\\\\xb2RPJ\\\\xcb\\\\xcfOJ,R\\\\xaa\\\\x05\\\\x00T\\\\x83\\\\x07b'"
問題是,是否可以將其轉換回字節類型以便我可以解壓縮它? 如果是這樣,如何?
我已經看到了一些不同的例子(例如, 如何將字符串強制轉換為字節而不進行編碼)對於我正在嘗試的內容並不完全有效。
更新:
很多好的答案,謝謝大家! 我希望我可以點擊其中的多個接受。 是的,正如你們許多人所指出的,它是 zlib 壓縮的。 這是設計使然,因為我們的工作空間極其有限,如果可能的話,我們希望繼續使用 JSON(隨意選擇 zlib 只是為了消除二進制數據的怪癖,可能不是最終選擇)。
假設您的原始字符串為str
類型,您有以下原始字符串(文字長度為 4 的轉義碼,而不是代表 1 個字節的實際轉義碼):
s = r"b'x\x9c\xabV*HL\xd1\xcd\xccK\xcbW\xb2RPJ\xcb\xcfOJ,R\xaa\x05\x00T\x83\x07b'"
如果刪除前導b'
和'
,則可以使用latin1
編碼轉換為字節。 latin1
是 Unicode 代碼點到字節值的 1:1 映射,因為前 256 個 Unicode 代碼點代表latin1
字符集:
>>> s[2:-1].encode('latin1')
b'x\\x9c\\xabV*HL\\xd1\\xcd\\xccK\\xcbW\\xb2RPJ\\xcb\\xcfOJ,R\\xaa\\x05\\x00T\\x83\\x07b'
這現在是一個字節字符串,但包含文字轉義碼。 現在應用unicode_escape
編碼轉換回實際代碼點的str
:
>>> s2 = b.decode('unicode_escape')
>>> s2
'x\x9c«V*HLÑÍÌKËW²RPJËÏOJ,Rª\x05\x00T\x83\x07b'
這現在是一個帶有代碼點的 Unicode 字符串,但我們仍然需要一個字節字符串。 再次使用latin1
編碼:
>>> b2 = s2.encode('latin1')
>>> b2
b'x\x9c\xabV*HL\xd1\xcd\xccK\xcbW\xb2RPJ\xcb\xcfOJ,R\xaa\x05\x00T\x83\x07b'
一步:
>>> s = r"b'x\x9c\xabV*HL\xd1\xcd\xccK\xcbW\xb2RPJ\xcb\xcfOJ,R\xaa\x05\x00T\x83\x07b'"
>>> b = s[2:-1].encode('latin1').decode('unicode_escape').encode('latin1')
>>> b
b'x\x9c\xabV*HL\xd1\xcd\xccK\xcbW\xb2RPJ\xcb\xcfOJ,R\xaa\x05\x00T\x83\x07b'
看起來這個示例數據是一個 zlib 壓縮的 JSON 字符串:
>>> import zlib,json
>>> json.loads(zlib.decompress(b))
{'pad-info': 'foobar'}
您可以通過選擇除前兩個b'
和最后一個'
字符之外的整個字符串來從字符串中獲取字節。 然后首先將其轉換為字節,然后再解碼回字符串。
這里有一個例子:
str(bytes(bytes_string[2:-1], encoding), encoding)
在哪里:
bytes_string = "b'x\x9c\xabV*HL\xd1\xcd\xccK\xcbW\xb2RPJ\xcb\xcfOJ,R\xaa\x05\x00T\x83\x07b'"
編碼是字節字符串中使用的編碼(例如'UTF-8')
黑盒服務器在發送之前對字節進行字符串化。 您需要獲取代表字節的字符串並將其轉換回字節。 最簡單的方法是使用抽象語法樹庫 (ast)。
import ast
import zlib
stringified_bytes = "b'x\\x9c\\xabV*HL\\xd1\\xcd\\xccK\\xcbW\\xb2RPJ\\xcb\\xcfOJ,R\\xaa\\x05\\x00T\\x83\\x07b'"
print(f"{type(stringified_bytes)}: {stringified_bytes}")
actual_bytes = ast.literal_eval(stringified_bytes)
print(f"{type(actual_bytes)}: {actual_bytes}")
answer = zlib.decompress(actual_bytes)
print(f"Answer: {answer}")
這是腳本的運行:
(venv) [ttucker@zim stackoverflow]$ python bin.py
<class 'str'>: b'x\x9c\xabV*HL\xd1\xcd\xccK\xcbW\xb2RPJ\xcb\xcfOJ,R\xaa\x05\x00T\x83\x07b'
<class 'bytes'>: b'x\x9c\xabV*HL\xd1\xcd\xccK\xcbW\xb2RPJ\xcb\xcfOJ,R\xaa\x05\x00T\x83\x07b'
Answer: b'{"pad-info": "foobar"}'
......這是非常有趣的東西......看起來他們有另一個帶有JSON的字節字符串。 這就像黑客編碼挑戰之一嗎?
我知道這是因為數據的開頭兩個字節是78 9c
( x
= 78
十六進制)......如果你在這里查看: https : //en.wikipedia.org/wiki/List_of_file_signatures ,你可以看到它是一個拉鏈
所以,我使用 zlib 庫來解碼它......整潔的東西。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.