一个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' )
就这么简单。