GB2312是基本的汉字编码集,通过GB2312编码表里的汉字编码规则,生成随机的汉字编码,再通过Encoding类进行转换,可以达到生成随机汉字的目的。
GB2312的汉字编码由区域码和位置码两部分组成,如汉字“好”的十六进制区域码是ba,十六进制位置码是c3
Encoding ed = Encoding.GetEncoding("GB2312"); byte[] bytes = ed.GetBytes("好"); Trace.WriteLine("ok"); foreach (byte b in bytes) { Trace.WriteLine(b.ToString("x")); }
从GB2312编码表中可以观察到汉字都从第16区B0开始,并且从区位D7开始以后的汉字都是和很难见到的繁杂汉字,所以随机生成的汉字十六进制区位码第1位范围在B、C、D之间,并且如果第1位是D的话,第2位区位码就不能是7以后的十六进制数。
在位置码方面,通过GB2312编码表可以发现每区的第一个位置和最后一个位置都是空的,没有汉字,因此随机生成的区位码第3位如果是A的话,第4位就不能是0,第3位如果是F的话,第4位就不能是F。
private string RandCN(uint len) { char[] hexChars = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; string retStr = string.Empty; Encoding ed = Encoding.GetEncoding("GB2312"); if (ed == null) //系统不支持GB2312 { return string.Empty; } for (int i = 0; i < len; i++) { //区码第一位字符:B-D Random rnd = new Random(); int r = rnd.Next(11, 14); char r1 = hexChars[r]; //区码第二位字符:0-7 rnd = new Random(r * unchecked((int)DateTime.Now.Ticks) + i); //重置随机种子 if (r == 13) { //如果第一位是D则第二位范围应是0-7 r = rnd.Next(0, 8); } else { r = rnd.Next(0, 16); } char r2 = hexChars[r]; //位码第一位字符:A-F rnd = new Random(r * unchecked((int)DateTime.Now.Ticks) + i); r = rnd.Next(10, 16); char r3 = hexChars[r]; //位码第二位字符:如果第一位为A则第二位不能为0,如果第一位为F则第二位不能为F rnd = new Random(r * unchecked((int)DateTime.Now.Ticks) + i); if (r == 10) //A { r = rnd.Next(1, 16); } else if (r == 15) //F { r = rnd.Next(0, 15); } else //B-E { r = rnd.Next(0, 16); } char r4 = hexChars[r]; byte b1 = Convert.ToByte(r1.ToString() + r2.ToString(), 16); byte b2 = Convert.ToByte(r3.ToString() + r4.ToString(), 16); byte[] bytes = new byte[] { b1, b2 }; retStr += ed.GetString(bytes); } return retStr; }
参考资料:
GB2312简体中文编码表
http://www.onejava.com/article/gb2312.htm
用C#生成随机中文汉字验证码的基本原理
http://www.codesky.net/article/doc/200804/2008041882518155.htm