• lua之base64的解码和编码(三种方案实现)


    概述

    由于涉及到java 与 lua 之间传递字节数组,如果直接传递的话会导致json解析失败,所以需要将字节数组加密为字符串,这样可以保证数据的完整传输。
    在网上找到了多个版本的lua base64的编解码代码,经过逐个测试最终方案3解决了我的问题。

    方案1:

    调用decodeBase64解码测试的时候经常返回nil值
    参考:http://www.cnblogs.com/decode1234/p/8505001.html

    -- lbase64加密和解密算法
    local function encodeBase64(source_str)
        local b64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
        local s64 = ''
        local str = source_str
    
        while #str > 0 do
            local bytes_num = 0
            local buf = 0
    
            for byte_cnt=1,3 do
                buf = (buf * 256)
                if #str > 0 then
                    buf = buf + string.byte(str, 1, 1)
                    str = string.sub(str, 2)
                    bytes_num = bytes_num + 1
                end
            end
    
            for group_cnt=1,(bytes_num+1) do
                local b64char = math.fmod(math.floor(buf/262144), 64) + 1
                s64 = s64 .. string.sub(b64chars, b64char, b64char)
                buf = buf * 64
            end
    
            for fill_cnt=1,(3-bytes_num) do
                s64 = s64 .. '='
            end
        end
    
        return s64
    end
    
    local function decodeBase64(str64)
        local b64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
        local temp={}
        for i=1,64 do
            temp[string.sub(b64chars,i,i)] = i
        end
        temp['=']=0
        local str=""
        for i=1,#str64,4 do
            if i>#str64 then
                break
            end
            local data = 0
            local str_count=0
            for j=0,3 do
                local str1=string.sub(str64,i+j,i+j)
                if not temp[str1] then
                    return
                end
                if temp[str1] < 1 then
                    data = data * 64
                else
                    data = data * 64 + temp[str1]-1
                    str_count = str_count + 1
                end
            end
            for j=16,0,-8 do
                if str_count > 0 then
                    str=str..string.char(math.floor(data/math.pow(2,j)))
                    data=math.mod(data,math.pow(2,j))
                    str_count = str_count - 1
                end
            end
        end
    
        local last = tonumber(string.byte(str, string.len(str), string.len(str)))
        if last == 0 then
            str = string.sub(str, 1, string.len(str) - 1)
        end
        return str
    end
    View Code

    方案2:

    参考:http://www.cnblogs.com/sjns/p/9958737.html

    测试ZZBase64.decode解码的时候,提示local num = a * 262144 + b * 4096 + c * 64 + d语句中的a为nil值

    ZZBase64 = {}
    local string = string
    
    ZZBase64.__code = {
        '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', '+', '/',
    };
    ZZBase64.__decode = {}
    for k,v in pairs(ZZBase64.__code) do
        ZZBase64.__decode[string.byte(v,1)] = k - 1
    end
    
    function ZZBase64.encode(text)
        local len = string.len(text)
        local left = len % 3
        len = len - left
        local res = {}
        local index  = 1
        for i = 1, len, 3 do
            local a = string.byte(text, i )
            local b = string.byte(text, i + 1)
            local c = string.byte(text, i + 2)
            -- num = a<<16 + b<<8 + c
            local num = a * 65536 + b * 256 + c
            for j = 1, 4 do
                --tmp = num >> ((4 -j) * 6)
                local tmp = math.floor(num / (2 ^ ((4-j) * 6)))
                --curPos = tmp&0x3f
                local curPos = tmp % 64 + 1
                res[index] = ZZBase64.__code[curPos]
                index = index + 1
            end
        end
        
        if left == 1 then
            ZZBase64.__left1(res, index, text, len)
        elseif left == 2 then
            ZZBase64.__left2(res, index, text, len)
        end
        return table.concat(res)
    end
    
    function ZZBase64.__left2(res, index, text, len)
        local num1 = string.byte(text, len + 1)
        num1 = num1 * 1024 --lshift 10
        local num2 = string.byte(text, len + 2)
        num2 = num2 * 4 --lshift 2
        local num = num1 + num2
        
        local tmp1 = math.floor(num / 4096) --rShift 12
        local curPos = tmp1 % 64 + 1
        res[index] = ZZBase64.__code[curPos]
        
        local tmp2 = math.floor(num / 64)
        curPos = tmp2 % 64 + 1
        res[index + 1] = ZZBase64.__code[curPos]
        
        curPos = num % 64 + 1
        res[index + 2] = ZZBase64.__code[curPos]
        
        res[index + 3] = "="
    end
    
    function ZZBase64.__left1(res, index,text, len)
        local num = string.byte(text, len + 1)
        num = num * 16
        
        tmp = math.floor(num / 64)
        local curPos = tmp % 64 + 1
        res[index ] = ZZBase64.__code[curPos]
        
        curPos = num % 64 + 1
        res[index + 1] = ZZBase64.__code[curPos]
        
        res[index + 2] = "="
        res[index + 3] = "="
    end
    
    function ZZBase64.decode(text)
        local len = string.len(text)
        local left = 0
        if string.sub(text, len - 1) == "==" then
            left = 2
            len = len - 4
        elseif string.sub(text, len) == "=" then
            left = 1
            len = len - 4
        end
        
        local res = {}
        local index = 1
        local decode = ZZBase64.__decode
        for i =1, len, 4 do
            local a = decode[string.byte(text,i    )]
            local b = decode[string.byte(text,i + 1)]
            local c = decode[string.byte(text,i + 2)]
            local d = decode[string.byte(text,i + 3)]
            
            --num = a<<18 + b<<12 + c<<6 + d
            local num = a * 262144 + b * 4096 + c * 64 + d
            
            local e = string.char(num % 256)
            num = math.floor(num / 256)
            local f = string.char(num % 256)
            num = math.floor(num / 256)
            res[index ] = string.char(num % 256)
            res[index + 1] = f
            res[index + 2] = e
            index = index + 3
        end
        
        if left == 1 then
            ZZBase64.__decodeLeft1(res, index, text, len)
        elseif left == 2 then
            ZZBase64.__decodeLeft2(res, index, text, len)
        end
        return table.concat(res)
    end
    
    function ZZBase64.__decodeLeft1(res, index, text, len)
        local decode = ZZBase64.__decode
        local a = decode[string.byte(text, len + 1)]
        local b = decode[string.byte(text, len + 2)]
        local c = decode[string.byte(text, len + 3)]
        local num = a * 4096 + b * 64 + c
        
        local num1 = math.floor(num / 1024) % 256
        local num2 = math.floor(num / 4) % 256
        res[index] = string.char(num1)
        res[index + 1] = string.char(num2)
    end
    
    function ZZBase64.__decodeLeft2(res, index, text, len)
        local decode = ZZBase64.__decode
        local a = decode[string.byte(text, len + 1)]
        local b = decode[string.byte(text, len + 2)]
        local num = a * 64 + b
        num = math.floor(num / 16)
        res[index] = string.char(num)
    end
    
    return ZZBase64
    View Code

    方案3:

    http://lua-users.org/wiki/BaseSixtyFour
    测试编解码ok

    base64 = {}
    
    local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' -- You will need this for encoding/decoding
    
    -- encoding
    function base64.enc(data)
        return ((data:gsub('.', function(x) 
            local r,b='',x:byte()
            for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end
            return r;
        end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x)
            if (#x < 6) then return '' end
            local c=0
            for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end
            return b:sub(c+1,c+1)
        end)..({ '', '==', '=' })[#data%3+1])
    end
    
    -- decoding
    function base64.dec(data)
        data = string.gsub(data, '[^'..b..'=]', '')
        return (data:gsub('.', function(x)
            if (x == '=') then return '' end
            local r,f='',(b:find(x)-1)
            for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end
            return r;
        end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x)
            if (#x ~= 8) then return '' end
            local c=0
            for i=1,8 do c=c+(x:sub(i,i)=='1' and 2^(8-i) or 0) end
                return string.char(c)
        end))
    end
    
    return base64
    View Code
  • 相关阅读:
    与众不同 windows phone (50)
    与众不同 windows phone (49)
    重新想象 Windows 8.1 Store Apps (93)
    重新想象 Windows 8.1 Store Apps 系列文章索引
    重新想象 Windows 8.1 Store Apps (92)
    重新想象 Windows 8.1 Store Apps (91)
    重新想象 Windows 8.1 Store Apps (90)
    重新想象 Windows 8.1 Store Apps (89)
    重新想象 Windows 8.1 Store Apps (88)
    重新想象 Windows 8.1 Store Apps (87)
  • 原文地址:https://www.cnblogs.com/7qin/p/13511348.html
Copyright © 2020-2023  润新知