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