本文共 4928 字,大约阅读时间需要 16 分钟。
最近在研究如何使用纯lua实现base64自定义码表编解码,记录一下。一起探讨下。
-- 自定义编码表local encodeTable = { [0] = 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/',}-- 字符串编码local function base64Encode(s) local bs = encodeTable local byte, rep = string.byte, string.rep local pad = 2 - ((#s-1) % 3) s = (s..rep('\0', pad)):gsub("...", function(cs) local a, b, c = byte(cs, 1, 3) return bs[a>>2] .. bs[(a&3)<<4|b>>4] .. bs[(b&15)<<2|c>>6] .. bs[c&63] end) return s:sub(1, #s-pad) .. rep('=', pad)end
参考:
-- 自定义解码表local decodeTable = { [0] = 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/',}local decodeArr = {[0] = -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1}-- 字节转换local function transferBytes(arr) local ss = {} local k = 1 while true do if k > #arr then break end local c = arr[k] if not c then break end if c<192 then table.insert(ss, string.char(c)) k = k + 1 elseif c<224 then k = k + 2 elseif c<240 then if c>=228 and c<=233 then local c1 = arr[k+1] local c2 = arr[k+2] if c1 and c2 then local a1,a2,a3,a4 = 128,191,128,191 if c == 228 then a1 = 184 elseif c == 233 then a2,a4 = 190,c1 ~= 190 and 191 or 165 end if c1>=a1 and c1<=a2 and c2>=a3 and c2<=a4 then table.insert(ss, string.char(c,c1,c2)) end end end k = k + 3 elseif c<248 then k = k + 4 elseif c<252 then k = k + 5 elseif c<254 then k = k + 6 end end return table.concat(ss)end-- 字符串解码local function base64Decode(s) local bs = decodeTable local byte, rep = string.byte, string.rep local pad = 0 local lastTwoString = string.sub(s, -2) local lastString = string.sub(s, -1) if lastTwoString == '==' then pad = 2 elseif lastString == '=' then pad = 1 end s = (s..rep('\0', pad)):gsub('....', function (cs) local a, b, c, d = byte(cs, 1, 4) local aStr, bStr, cStr, dStr = '', '', '', '' if decodeArr[a] and bs[decodeArr[a]] then aStr = bs[decodeArr[a]] end if decodeArr[b] and bs[decodeArr[b]] then bStr = bs[decodeArr[b]] end if decodeArr[c] and bs[decodeArr[c]] then cStr = bs[decodeArr[c]] end if decodeArr[d] and bs[decodeArr[d]] then dStr = bs[decodeArr[d]] end return aStr .. bStr .. cStr .. dStr end) -- 自定义码表转换后的字符串 local newStr = s:sub(1, #s-pad) .. rep('=', pad) local c1, c2, c3, c4 = -1, -1, -1, -1 local len = #newStr local decodeStr = '' local i = 1 local byteArr = {} local byteA, byteB, byteC = 0, 0, 0 while i <= len do -- c1 while i <= len do c1 = decodeArr[byte(newStr, i, i+1)] & 0xff i = i + 1 if c1 ~= -1 then break end end if c1 == -1 then break end -- c2 while i <= len do c2 = decodeArr[byte(newStr, i, i+1)] & 0xff i = i + 1 if c2 ~= -1 then break end end if c2 == -1 then break end byteA = (c1<<2)|(c2&0x30)>>4 table.insert(byteArr, byteA) -- c3 while i <= len do c3 = byte(newStr, i, i+1) & 0xff i = i + 1 if c3 == 61 then return decodeStr end c3 = decodeArr[c3] if c3 ~= -1 then break end end if c3 == -1 then break end byteB = ((c2&0xF)<<4)|((c3&0x3C)>>2) table.insert(byteArr, byteB) -- c4 while i <= len do c4 = byte(newStr, i, i+1) & 0xff i = i + 1 if c4 == 61 then return decodeStr end c4 = decodeArr[c4] if c4 ~= -1 then break end end if c4 == -1 then break end byteC = ((c3&0x03)<<6)|c4 table.insert(byteArr, byteC) end decodeStr = transferBytes(byteArr) return decodeStrend
转载地址:http://pdktn.baihongyu.com/