Base24编码C#类库

Base24编码一般用于序列号的生成,在Base64编码的基础上去掉了特殊字符和容易混淆的字符,如1和l,0和O,Winxp和Office的序列号都是基于此编码(用25个base 24字符表示114 bits)。其基本原理是使用7个base24字符编码32bits,7个base24字符的数据范围是24的7次方也就是4,586,471,424,而32bits的数据范围是:4,294,967,296。能够包括所有数据且有一定余量。下面给出C#实现:

 

  1 //文件:Base24Encoding.cs
  2 //作者:blueqt
  3 //日期:2010-01-17
  4 //版本:1.0
  5 namespace System.Text
  6 {
  7     /// <summary>
  8     /// 表示 base 24 编码
  9     /// </summary>
 10     public class Base24Encoding
 11     {
 12         /// <summary>
 13         /// 表示 base 24 编码的默认实现使用的字符映射表:BCDFGHJKMPQRTVWXY2346789
 14         /// </summary>
 15         public const string DefaultMap = "BCDFGHJKMPQRTVWXY2346789";
 16 
 17         private static Base24Encoding defaultInstance;
 18 
 19         private string map;
 20 
 21         /// <summary>
 22         /// 默认构造函数
 23         /// </summary>
 24         public Base24Encoding()
 25         {
 26             this.map = DefaultMap;
 27         }
 28 
 29         /// <summary>
 30         /// 获取 base 24 编码的默认实现
 31         /// </summary>
 32         public static Base24Encoding Default
 33         {
 34             get
 35             {
 36                 if (defaultInstance == null)
 37                 {
 38                     defaultInstance = new Base24Encoding();
 39                 }
 40                 return defaultInstance;
 41             }
 42         }
 43 
 44         /// <summary>
 45         /// 获取或设置进行 base 24 编码的字符映射表
 46         /// </summary>
 47         /// <exception cref="ArgumentException">map不符合规范:长度24不允许重复字符</exception>
 48         public string Map
 49         {
 50             get { return this.map; }
 51             set
 52             {
 53                 if (value == null || value.Length != 24)
 54                 {
 55                     throw new ArgumentException("map必须是长度24的字符串");
 56                 }
 57                 for (byte i = 1; i < 24; i++)
 58                 {
 59                     for (byte j = 0; j < i; j++)
 60                     {
 61                         if (value[i] == value[j])
 62                         {
 63                             throw new ArgumentException("map中不能含有重复字符");
 64                         }
 65                     }
 66                 }
 67                 this.map = value;
 68             }
 69         }
 70 
 71         /// <summary>
 72         /// 将 8 位无符号整数数组的值转换为它的等效 System.String 表示形式(使用 base 24 数字编码)。
 73         /// </summary>
 74         /// <param name="bytes">一个 8 位无符号整数数组。</param>
 75         /// <returns>bytes 内容的 System.String 表示形式,以基数为 24 的数字表示。</returns>
 76         /// <exception cref="ArgumentNullException">bytes 为 null。</exception>
 77         public string GetString(byte[] bytes)
 78         {
 79             if (bytes == null)
 80             {
 81                 throw new ArgumentNullException("bytes");
 82             }
 83             string text = string.Empty;
 84             for (int i = bytes.Length - 1; i >= 0; i -= 4)
 85             {
 86                 uint data = 0;
 87                 for (int j = i < 3 ? i : 3; j >= 0; j--)
 88                 {
 89                     data = (data << 8+ bytes[i - j];
 90                 }
 91 
 92                 string t = string.Empty;
 93                 while (data > 0)
 94                 {
 95                     int d = (int)(data % 24);
 96                     t = map[d] + t;
 97                     data = data / 24;
 98                 }
 99                 text = t.PadLeft(7, map[0]) + text;
100             }
101             return text;
102         }
103 
104         /// <summary>
105         /// 将指定的 System.String(它将二进制数据编码为 base 24 数字)转换成等效的 8 位无符号整数数组。
106         /// </summary>
107         /// <param name="text">System.String。</param>
108         /// <returns>等效于 text 的 8 位无符号整数数组。</returns>
109         /// <exception cref="ArgumentNullException">text 为 null。</exception>
110         /// <exception cref="FormatException">text 包含非 base 24 字符 或 text 包含不可转换的 base 24 字符序列</exception>
111         public byte[] GetBytes(string text)
112         {
113             if (text == null)
114             {
115                 throw new ArgumentNullException("text");
116             }
117             int len = text.Length / 7 + (text.Length % 7 == 0 ? 0 : 1);
118             byte[] bytes = new byte[len * 4];
119             int pos = bytes.Length - 1;
120             for (int i = text.Length - 1; i >= 0; i -= 7, pos -= 4)
121             {
122                 uint data = 0;
123                 for (int j = i < 6 ? i : 6; j >= 0; j--)
124                 {
125                     int d = map.IndexOf(text[i - j]);
126                     if (d == -1)
127                     {
128                         throw new FormatException("text 包含非 base 24 字符");
129                     }
130                     try
131                     {
132                         data = checked(data * 24 + (uint)d);
133                     }
134                     catch (OverflowException)
135                     {
136                         throw new FormatException("text 包含不可转换的 base 24 字符序列");
137                     }
138                 }
139 
140                 byte[] t = BitConverter.GetBytes(data);
141                 for (int j = 0; j < 4; j++)
142                 {
143                     bytes[pos - j] = t[j];
144                 }
145             }
146             return bytes;
147         }
148     }
149 }
150 

 

 

使用示例如下:

 

 1         private void button1_Click(object sender, EventArgs e)
 2         {
 3             string[] t = this.textBox2.Text.Split(',');
 4             byte[] data = new byte[t.Length];
 5             for (int i = 0; i < t.Length; i++)
 6             {
 7                 data[i] = byte.Parse(t[i]);
 8             }
 9             string text = Base24Encoding.Default.GetString(data);
10             text = text.TrimStart(Base24Encoding.DefaultMap[0]);
11             text = text.PadLeft(25, Base24Encoding.DefaultMap[0]);
12             for (int i = text.Length - 5; i > 0; i -= 5)
13             {
14                 text = text.Insert(i, "-");
15             }
16             this.textBox1.AppendText(text + "\r\n");
17         }
18 
19         private void button2_Click(object sender, EventArgs e)
20         {
21             try
22             {
23                 string t = this.textBox2.Text.Replace("-""");
24                 byte[] data = Base24Encoding.Default.GetBytes(t);
25                 string text = "";
26                 for (int i = 0; i < data.Length; i++)
27                 {
28                     text += "," + data[i].ToString();
29                 }
30                 if (text.Length > 0) text = text.Substring(1);
31                 this.textBox1.AppendText(text + "\r\n");
32             }
33             catch (Exception ex)
34             {
35                 this.textBox1.AppendText(ex.Message + "\r\n");
36             }
37         }
38 

运行结果:有效数据114bits

输入:0,3,50,52,24,23,49,50,52,24,23,49,50,52,24,23

输出:XFXTD-D3HCQ-DGV3J-83CGP-3YQY9

posted @ 2014-06-08 10:34  zzg168  阅读(308)  评论(0)    收藏  举报