使用 C# 实现 URL 安全的 Base62 转码

Base62 编码与 Base64 编码类似,都用于数据内容编码。Base64 和 Base62 的目的在都在于将需要传输的内容进行编码,尤其是一些特殊字符(如不可见字符、传输时与协议头冲突的字符)。

与 Base64 不同的是,Base62 编码是由10个数字、26个大写英文字母和26个小写英文字母组成,不包含 Base64 中的符号:+,/和=。这让经过 Base62 编码的数据很适合在 URL 中进行传输。

微信的扫码登录规定了 state 只能使用 a-zA-Z0-9 的参数值,这种场景下使用 Base62 就很有效。

public static class Base62
{
    private const string DefaultCharacterSet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    private const string InvertedCharacterSet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";




    /// <summary>
    /// Encode a byte array with Base62
    /// </summary>
    /// <param name="original">Byte array</param>
    /// <param name="inverted">Use inverted character set</param>
    /// <returns>Base62 string</returns>
    public static string ToBase62(byte[] original, bool inverted = false)
    {
        var characterSet = inverted ? InvertedCharacterSet : DefaultCharacterSet;
        var arr = Array.ConvertAll(original, t => (int)t);


        var converted = BaseConvert(arr, 256, 62);
        var builder = new StringBuilder();
        foreach (var t in converted)
        {
            builder.Append(characterSet[t]);
        }
        return builder.ToString();
    }


    /// <summary>
    /// Decode a base62-encoded string
    /// </summary>
    /// <param name="base62">Base62 string</param>
    /// <param name="inverted">Use inverted character set</param>
    /// <returns>Byte array</returns>
    public static byte[] FromBase62(string base62, bool inverted = false)
    {
        if (string.IsNullOrWhiteSpace(base62))
        {
            throw new ArgumentNullException(nameof(base62));
        }


        var characterSet = inverted ? InvertedCharacterSet : DefaultCharacterSet;
        var arr = Array.ConvertAll(base62.ToCharArray(), characterSet.IndexOf);


        var converted = BaseConvert(arr, 62, 256);
        return Array.ConvertAll(converted, Convert.ToByte);
    }


    private static int[] BaseConvert(int[] source, int sourceBase, int targetBase)
    {
        var result = new List<int>();
        var leadingZeroCount = Math.Min(source.TakeWhile(x => x == 0).Count(), source.Length - 1);
        int count;
        while ((count = source.Length) > 0)
        {
            var quotient = new List<int>();
            var remainder = 0;
            for (var i = 0; i != count; i++)
            {
                var accumulator = source[i] + remainder * sourceBase;
                var digit = accumulator / targetBase;
                remainder = accumulator % targetBase;
                if (quotient.Count > 0 || digit > 0)
                {
                    quotient.Add(digit);
                }
            }


            result.Insert(0, remainder);
            source = quotient.ToArray();
        }
        result.InsertRange(0, Enumerable.Repeat(0, leadingZeroCount));
        return result.ToArray();
    }
}

将字节数组转换为 Base62 字符串

var guid = Guid.Parse("40943a11e5434d2f869d4e566e48c4f2");
Console.WriteLine(Base62.ToBase62(guid.ToByteArray()));

输出:

WVdhFoDbSqBBYSKzptnko

将 Base62 字符串转换为字节数组

var str = "WVdhFoDbSqBBYSKzptnko";
var bytes = Base62.FromBase62(str);
var guid = new Guid(bytes);
Console.WriteLine(guid.ToString("N"));

输出:

40943a11e5434d2f869d4e566e48c4f2
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值