1.纯lua的二进制位操作
lua的二进制文件主要利用string.byte()读取某个字节,string.char()写入,示例代码如下:
function v:xorFile(inputFile,outputFile)
local fileIn,err = io.open(inputFile,"rb")
local content = fileIn:read("*all")
local length = fileIn:seek("end")
fileIn:close()
local fileOut,err = io.open(outputFile,"wb")
fileOut:seek("set",0)
local item
for i=1,length do
item = tonumber(string.byte(content,i))
item = bit:_xor(item,186)
fileOut:write(string.char(item))
end
fileOut:close()
end
这是对整个二进制文件进行异或操作,那么对某个32位的uint如何操作?比如把第posSrc位的uint32异或posDst位的uint32
function v:XORuint32(inputFile,outputFile,posSrc,posDst)
local fileIn,err = io.open(inputFile,"rb")
local content = fileIn:read("*all")
local length = fileIn:seek("end")
fileIn:seek("set",0)
local dataA = fileIn:read(posSrc-1)
fileIn:seek("set",posSrc+4)
local dataB = fileIn:read("*all")
fileIn:close()
local value1 = tonumber(string.byte(content,posSrc+1))
local value2 = tonumber(string.byte(content,posSrc+2))
local value3 = tonumber(string.byte(content,posSrc+3))
local value4 = tonumber(string.byte(content,posSrc+4))
local key1 = tonumber(string.byte(content,posDst+1))
local key2 = tonumber(string.byte(content,posDst+2))
local key3 = tonumber(string.byte(content,posDst+3))
local key4 = tonumber(string.byte(content,posDst+4))
value1 = bit:_xor(value1,key1)
value2 = bit:_xor(value2,key2)
value3 = bit:_xor(value3,key3)
value1 = bit:_xor(value4,key4)
local fileOut,err = io.open(outputFile,"wb")
fileOut:seek("set",0)
fileOut:write(dataA)
fileOut:write(string.char(value1))
fileOut:write(string.char(value2))
fileOut:write(string.char(value3))
fileOut:write(string.char(value4))
fileOut:write(dataB)
fileOut:close()
end
附上bit的代码
bit={data32={}}
for i=1,32 do
bit.data32[i]=2^(32-i)
end
function bit:d2b(arg)
local tr={}
for i=1,32 do
if arg >= self.data32[i] then
tr[i]=1
arg=arg-self.data32[i]
else
tr[i]=0
end
end
return tr
end --bit:d2b
function bit:b2d(arg)
local nr=0
for i=1,32 do
if arg[i] ==1 then
nr=nr+2^(32-i)
end
end
return nr
end --bit:b2d
function bit:_xor(a,b)
local op1=self:d2b(a)
local op2=self:d2b(b)
local r={}
for i=1,32 do
if op1[i]==op2[i] then
r[i]=0
else
r[i]=1
end
end
return self:b2d(r)
end --bit:xor
function bit:_and(a,b)
local op1=self:d2b(a)
local op2=self:d2b(b)
local r={}
for i=1,32 do
if op1[i]==1 and op2[i]==1 then
r[i]=1
else
r[i]=0
end
end
return self:b2d(r)
end --bit:_and
function bit:_or(a,b)
local op1=self:d2b(a)
local op2=self:d2b(b)
local r={}
for i=1,32 do
if op1[i]==1 or op2[i]==1 then
r[i]=1
else
r[i]=0
end
end
return self:b2d(r)
end --bit:_or
function bit:_not(a)
local op1=self:d2b(a)
local r={}
for i=1,32 do
if op1[i]==1 then
r[i]=0
else
r[i]=1
end
end
return self:b2d(r)
end --bit:_not
function bit:_rshift(a,n)
local op1=self:d2b(a)
local r=self:d2b(0)
if n < 32 and n > 0 then
for i=1,n do
for i=31,1,-1 do
op1[i+1]=op1[i]
end
op1[1]=0
end
r=op1
end
return self:b2d(r)
end --bit:_rshift
function bit:_lshift(a,n)
local op1=self:d2b(a)
local r=self:d2b(0)
if n < 32 and n > 0 then
for i=1,n do
for i=1,31 do
op1[i]=op1[i+1]
end
op1[32]=0
end
r=op1
end
return self:b2d(r)
end --bit:_lshift
function bit:print(ta)
local sr=""
for i=1,32 do
sr=sr..ta[i]
end
print(sr)
end
以上代码异或整个文件,1M的文件需要15秒左右,显然太慢,于是换个脚本,用python试试
2.python的二进制位操作
import binascii
import struct
import sys
def str2hex(str):
hexs = []
for s in str:
tmp = (hex(ord(s)).replace('0x',''))
if len(tmp) == 2:
hexs.append(tmp)
else:
hexs.append('0'+tmp)
return hexs
arr= ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f']
arr2 = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
def tran(r):
for i in range(len(arr)):
if r == arr[i]:
return arr2[i]
def packRes(input,output,key):
f = open(input,'rb+')
hexs = []
while True:
t = f.read(1)
if len(t) == 0:
break
hexs.extend(str2hex(t))
f.close()
ff = open(output,'wb')
for i in range(len(hexs)):
a = tran(hexs[i][0])*16+tran(hexs[i][1])
B = struct.pack('B',a^key)
ff.write(B)
ff.close()
def main(p1,p2,p3):
print(p1)
print(p2)
print(p3)
try:
packRes(p1,p2,int(p3))
sys.exit(0)
except:
sys.exit(1)
finally:
pass
if __name__ == "__main__":
if len(sys.argv) >= 1:
p1 = sys.argv[1]
p2 = sys.argv[2]
p3 = sys.argv[3]
main(p1,p2,p3)
同样的文件要1秒左右,效率提升显著,然而还是不满足需求,还是试试C++吧
3.c++的二进制位操作
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cstdlib>
int main(int argc, char* argv[])
{
int i, count, len;
int key;
char buff[1024];
static char tmpfile[] = "~u~0_sw~.f~l";
FILE * in, *out;
if (argc <3)
{
printf("Less Parameter !\n");
printf("Parameter number must at least 2 !!\n");
return 1;
}
len = strlen(argv[2]);
in = fopen(argv[1], "rb");
out = fopen(tmpfile, "wb"); /* creat a temp file */
key = std::atoi(argv[3]);
if (in == NULL)
{
printf("Input File \'%s\' not found !!\n", argv[1]);
exit(1);
}
if (out == NULL)
{
printf("Can not creat temp file \'%s\'\n", tmpfile);
exit(2);
}
while (!feof(in))
{
count = fread(buff, 1, 1024, in);
for (i = 0;i <count;i++)
buff[i] ^= 119;
//buff[i] ^= argv[2][i%len];
fwrite(buff, 1, count, out);
}
fclose(in);
fclose(out);
//printf(argv[1]);
//printf(argv[2]);
if( strcmp(argv[1], argv[2]) == 0)
{
remove(argv[1]);
printf("the key is: %d", key);
}
rename(tmpfile, argv[2]);
return 0;
}
注意再创建控制台应用程序的设置,不要预编译头,否则cpp在MAC下会不兼容。
1M左右,大概需要0.0006秒左右。因为我们最终是在lua脚本里用,所以接下来说下lua如何调用python
4.lua调用python和C
lua里面用os.excute来调用本地脚本。
首先看下调用python,由于python是跨平台的,MAC和WIN10下代码一致:
os.excute("python xxx.py inputFIle outputFile key")
在win10下调用控制台程序的话:VS新建控制台应用程序,调试成功后cd到exe 目录
os.excute("xxx.exe inputFIle outputFile key")
在mac下先cd到cpp目录用g++编译
g++ xxx.cpp
生成a.out
os.excute("./a.out inputFIle outputFile key")
5.小结
有人会喜欢那语言做比较,我认为语言是看场合的,就像你比较匕首和导弹,没有太大的意义。主要看武器在谁的手里,怎么去使用它。
上面对比来看,貌似python比lua效率高很多,然而,我们本不该在lua里面执行大体积二进制文件的位操作,Lua作为C的触手,应该在C里面绑定一个方法让lua调用,这样lua的效率就是C的效率(当然,要扣除一点调用C的成本)。
lua和python在不同场合有着各自的生命力。