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
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
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