AMF中整形数值的转换方法
截取了一小段16进制的AMF3
数据「04 88 DB 34」,对应的整形10进制数值为「142772」,以下说明两者之间如何转换。
开头的「04」在AMF3
格式中表示当前值为整形数据,而「88 DB 34」则是UTF编码表示的具体整形数值。
二进制表示为:(UTF是变长编码,所以最后一个字节的最高位为0,用于表明结束当前值)
10001000 11011011 00110100
去掉每个字节的最高位,剩下21位:
0001000 1011011 0110100
从后面算起,每4位为一个新字节,重新排一下位置(还是21位):
0 0010 0010 1101 1011 0100
每4位转为一个16进制值显示,即:
0x22DB4
也就是10进制值:
142772
下面使用AAUTO编写转换的函数,分为繁琐的每步操作版和简化版,用于详细地了解数值是如何转换的。
16进制转整形(按步骤操作版):
var hex2int = function(value){
value = string.replace(value, "[\t\ \n]+", "") //删除多余的空白符号
value = (string.replace(value,".{2}",function(s){
return string.format("%08b", tonumber(s,16)) //16进制转为2进制格式
}))
value = (string.replace(value,".{8}",function(s){
return string.right(s,7) //去掉每个字节的最高位,即保留右7位
}))
value = string.repeat( 4 - (#value % 4), "0" ) ++ value //前面补0,为下方每4位处理作准备
value = (string.replace(value,".{4}",function(s){
return string.format( "%X", tonumber(s,2) ) //每四位2进制数转为16进制显示
}))
return ( tonumber(value,16) ); //按16进制转为10进制格式
}
16进制转整形(简化版,推荐):
var hex2int = function(value){
value = string.replace(value, "[\t\ \n]+", "") //删除多余的空白符号
value = string.format("%b", tonumber(value,16)) //16进制转为2进制格式
value = string.replace(value, ".(.{7})", "\1") //去掉每个字节的最高位,即保留右7位
return ( tonumber(value,2) ); //按2进制转为10进制格式并返回
}
整形转16进制(按步骤操作版):
var int2hex = function(value){
value = string.format("%X", tonumber(value))
value = string.replace(value,".",function(s){ //每个数转为四位的2进制值
return string.format("%04b", tonumber(s,16));
})
value = string.repeat( 7 - (#value % 7), "0" ) ++ value; //前面补0,为下面补最高位作准备
value = string.reverse(value) //反转字串,方便从后方开始补最高位
value = string.replace(value, ".{7}", function(s){
return s++"1"; //补最高位1
})
value = string.replace(value, "^(.{7})1", "\10") //第8位值需要为0,表示数值的结束
value = string.reverse(value) //补位完成,再反转为正常状态
return string.format("%02X", tonumber(value,2)); //返回16进制显示
}
整形转16进制(简化版,推荐):
var int2hex = function(value){
value = string.format("%b", value); //转为2进制
value = string.repeat( 7 - (#value % 7), "0" ) ++ value; //前面补0,为下面补最高位作准备
value = string.replace(value, "(.{7})", "1\1"); //每7位补一个最高位,用于生成新的字节
value = string.replace(value, "1(.{7})$", "0\1"); //末尾字节最高位为0,表示数值的结束
return string.format("%X", tonumber(value,2)); //返回16进制显示
}
关键是要了解UTF的解码方法(PS:大数值转换时以上算法需要改进,请自行对比二进制值即可找到原因)
UTF编码是变长的,用来表示整型数据时,最高位为1表示下面还有字节,为0表示已经到达最后一个字节了。
所以根据最高位可以判断这个数据的字节长度及是否到达结尾,然后去掉最高位后剩下的数据就是实际值了。
参考: AMF3协议中文版 - 百度文库 AMF数据解析的问题 - CSDN论坛 AMF学习2远程调用的封装 - 深蓝 谈AMF和AMF Message - 逆水行舟 【荐】