C#中有对应的Base64处理函数:例如把byte[] 转成base64字符串Convert.ToBase64String

base64是用64个字符来表示任意二进制数据的方法,它对二进制数据进行处理,它把每6bit前缀补0转成8bit后,再查base64字符表得到转化后的结果。

base64编码所用的64个字符为:A-Za-z0-9+/

base64URL编码基于base64编码,把字符+和/分别变成-和_。

同理:还有base58, base58去掉了0(数字0)、O (大写字母O)、 I (大写的字母i) and l (小写的字母L) 、/、 +等。

在java8中有对应的处理函数:Base64.getUrlEncoder().encodeToString

C#中没有找到对应的处理函数,基于以上理解可以直接做字符替换:

    string temp = Convert.ToBase64String(dataBytes);
    string basedTimeStr = temp.Replace("+", "-").Replace("/", "_");

应用实例:unix时间戳的编码成6位字符串的算法:

java代码为:
public class Base64URLEncoder {  
       public static String encode(long ts) {
             return Base64.getUrlEncoder().encodeToString(ByteBuffer.allocate(Long.BYTES).putLong((ts / 1000) << 28).array())
                          .substring(0, 6);        }
C#代码为:
/// <summary> /// 时间编码 /// </summary> /// <param name="dtNow">当前本地时间</param>
/// <returns></returns> string GetDate(DateTime dtNow) { DateTime dtStart = new
DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); TimeSpan span =
dtNow.ToUniversalTime() - dtStart; long currentTimeSeconds=
(long)(span.TotalSeconds) << 28; var dataBytes =
BitConverter.GetBytes(currentTimeSeconds); Array.Reverse(dataBytes); string
temp = Convert.ToBase64String(dataBytes); string basedTimeStr =
temp.Replace("+", "-").Replace("/", "_"); ; string result =
basedTimeStr.Substring(0, 6);//只返回前6位 return result; } /// <summary> /// 时间解码
/// </summary> /// <param name="code"></param> /// <returns>返回本地时间</returns>
DateTime DeCodeDate(string code) { byte[] bytes =
Convert.FromBase64String(code); Array.Reverse(bytes); ulong tt =
BitConverter.ToUInt64(bytes, 0); DateTime dtStart = new DateTime(1970, 1, 1, 0,
0, 0, DateTimeKind.Utc); //DateTime dtStart =
TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1, 0, 0, 0, 0));
long unixTime = (long)tt >> 28; return
dtStart.AddSeconds(unixTime).ToLocalTime(); }
对应的另外一种算法2,对64取模:
string s_base64url =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; string
GetDate2(DateTime dtNow) { DateTime dtStart = new DateTime(1970, 1, 1, 0, 0, 0,
DateTimeKind.Utc); TimeSpan span = dtNow.ToUniversalTime() - dtStart; long sek
=(long) Math.Floor(span.TotalSeconds); StringBuilder stringBuilder = new
StringBuilder(); while (sek > 0) { long n = sek % 64; char baseStr =
s_base64url[(int)n]; stringBuilder.Insert(0,baseStr); sek =
(long)Math.Floor((double)sek/64); } return
stringBuilder.ToString().PadLeft(6,'A'); }
 算法2的计算过程同base58的方式,之所以计算1和计算2结果相同,是因为本质都是64进制。

对算法1中左移28位(<<28)的理解:

因为base64是每6bit一个转码,如果需求是把时间戳转成6位字符,则时间戳从低位开始的6*6=36有效,剩下64-36=28位都是0,其他位都是1,则最大可表示的年月日为:4147/8/20
15:32:15
string longBinaryStr = "00000000 00000000 00000000 00001111 11111111 11111111
11111111 11111111".Replace(" ",""); long unixTime =
Convert.ToInt64(longBinaryStr, 2); DateTime dt =
dtStart.AddSeconds(unixTime).ToLocalTime();
 <<28

基于上面的理解:写一个解码函数:
private void DecodeBase64URLString(string code) { string s_base64url =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
StringBuilder sb = new StringBuilder(); for (int i = 0; i < 6; i++) { byte
ch_index = (byte)s_base64url.IndexOf(code[i]); string tempBinary =
Convert.ToString(ch_index, 2).PadLeft(6,'0'); sb.Append(tempBinary); } for (int
i = sb.Length; i < 64; i++) { sb.Append("0"); } long unix =
Convert.ToInt64(sb.ToString(), 2); DateTime dtStart = new DateTime(1970, 1, 1,
0, 0, 0, DateTimeKind.Utc); long test = (long)unix >> 28; DateTime dtR=
dtStart.AddSeconds(test).ToLocalTime(); this.txtDate.Text =
dtR.ToString("yyyy-MM-dd HH:mm:ss"); }

 

技术
下载桌面版
GitHub
百度网盘(提取码:draw)
Gitee
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:[email protected]
QQ群:766591547
关注微信