1. 程式人生 > >python 把string的值當做16進位制處理

python 把string的值當做16進位制處理

一個string的,因為某種原因我們需要將它的值看成hex來處理。

這個問題的上下文是這樣的。 我們公司有個一個APK Parser可以獲取APK的屬性,包括package Name, permissionName之類的,然後以XML文字的形式儲存起來。這裡出現了一些問題。就是APK的某些項包含特殊字元的時候,我們如果不作任何編碼直接放在XML檔案裡面可能會由於特殊字元的干擾造成XML檔案不被識別 (典型的特殊字元比如 ‘\’)。 於是我們的工程師就對所有的文字進行來了一次utf-16-le (UTF-16-LITTLE-ENDIAN)的編碼。然後在XML裡面的字串以編碼後的16進位制raw string來代替。e.g: 63006f006d002e006600370032003900300077006500690072002e0065006c00730066006b002e0074007800 表示com.f7290weir.elsfk.tx

但是我現在需要對這個已經編碼後的16進位制字串進行解析,進行一個逆向工程來得到原文。

str = 63006f006d002e006600370032003900300077006500690072002e0065006c00730066006b002e0074007800
print decode(str,'uft16')
>> ㌶〰昶〰搶〰攲〰㘶〰㜳〰㈳〰㤳〰〳〰㜷〰㔶〰㤶〰㈷〰攲〰㔶〰挶〰㌷〰㘶〰戶〰攲〰傌〰㠷〰

用以上方法明顯行不通。 因為我們是以little endian的方式編碼的,所以相對而言也需要以同樣的方式解碼。

str = 63006f006d002e006600370032003900300077006500690072002e0065006c00730066006b002e0074007800
print decode(str,'uft_16_el')
>>㌶〰昶〰搶〰攲〰㘶〰㜳〰㈳〰㤳〰〳〰㜷〰㔶〰㤶〰㈷〰攲〰㔶〰挶〰㌷〰㘶〰戶〰攲〰傌〰㠷〰
使用了little-endian任然有問題。在這個問題上我想到應該是由於我們的str並沒有被認為是16進位制的值,從而我們decode的物件實際上是string化的這麼一長串數字。

這個問題如何解決呢。對每兩位前面加一個"\x"是我們最容易想到的。

a = "63006f006d002e006600370032003900300077006500690072002e0065006c00730066006b002e0074007800"
retval = ''

for i in range ( 0, len( a ) / 2 ):
    retval = retval + '\x' + a[i * 2] + a[i * 2 + 1]

print [retval]
>>ValueError: invalid \x escape


很遺憾這個方法不行。 在我們寫下面那段程式碼的時候python就已經無法忍受的報錯了。

+ '\x' + 
這很可以理解,python直譯器無法認同''\x" 這種型別的空串。但是如果這不行的話我們還能有什麼方法表達String的值為16進位制碼呢。

其實很簡單,因為它是一個表示16進位制的字串。換句話說它也就是經過16進位制編碼過一次的string串兒。我們直接對它進行一次hex的解碼就行了。

a = "63006f006d002e006600370032003900300077006500690072002e0065006c00730066006b002e0074007800"
print a.decode( 'hex' ).decode( 'utf_16_le' ) 就這麼簡單。