当前位置: 首页 > 编程日记 > 正文

用C#生成随机中文汉字验证码的基本原理

前几天去申请免费QQ号码,突然发现申请表单中的验证码内容换成了中文,这叫真叫我大跌眼镜感到好笑,Moper上的猫儿们都大骂腾讯采用中文验证码。^_^
我不得不佩服腾讯为了防止目前网络上横行的QQ号码自动注册机而采取中文验证码的手段。仔细想了想感觉用程序生成随机的中文验证码并不是很难,下面就来介绍一下使用C#生成随机的中文汉字的原理。


1、汉字编码原理
到底怎么办到随机生成汉字的呢?汉字从哪里来的呢?是不是有个后台数据表,其中存放了所需要的所有汉字,使用程序随机取出几个汉字组合就行了呢?使用后台数据库先将所有汉字存起来使用时随机取出,这也是一种办法,但是中文汉字有这么多,怎么来制作呢?其实可以不使用任何后台数据库,使用程序就能做到这一切。要知道如何生成汉字,就得先了解中文汉字的编码原理。
1980年,为了使每一个汉字有一个全国统一的代码,我国颁布了第一个汉字编码的国家标准: GB2312-80《信息交换用汉字编码字符集》基本集,简称GB2312,这个字符集是我国中文信息处理技术的发展基础,也是国内所有汉字系统的统一标准。到了后来又公布了国家标准GB18030-2000《信息交换用汉字编码字符集基本集的扩充》,简称GB18030,编程时如果涉及到编码和本地化的朋友应该对GB18030很熟悉。这是是我国继GB2312-1980和GB13000-1993之后最重要的汉字编码标准,同时也是未来我国计算机系统必须遵循的基础性标准之一。
目前在中文WINDOWS操作系统中,.NET编程中默认的的代码页就是GB18030简体中文。但是事实上如果生成中文汉字验证码只须要使用GB2312字符集就已经足够了。字符集中除了我们平时大家都认识的汉字外,也包含了很多我们不认识平时也很少见到的汉字。如果生成中文汉字验证码中有很多我们不认识的汉字让我们输入,对于使用拼音输入法的朋友来说可不是好事,五笔使用者还能勉强根据汉字的长相打出来,呵呵!所以对于GB2312字符集中的汉字我们也不是全都要用。
中文汉字字符可以使用区位码来表示,见

汉字区位码表            http://navicy2005.home4u.china.com/resource/gb2312tbl.htm
汉字区位码代码表    http://navicy2005.home4u.china.com/resource/gb2312tbm.htm

其实这两个表是同一回事,只不过一个使用十六进制分区表示,一个使用区位所在的数字位置表示。 例如“好”字的十六进制区位码是ba c3,前两位是区域,后两位代表位置,ba处在第26区,“好”处在此区汉字的第35位也就是c3位置,所以数字代码就是2635。这就是GB2312汉字区位原理。根据《汉字区位码表 》我们可以发现第15区也就是AF区以前都没有汉字,只有少量符号,汉字都从第16区B0开始,这就是为什么GB2312字符集都是从16区开始的。

2、.Net程序处理汉字编码原理分析
在.Net中可以使用System.Text来处理所有语言的编码。在System.Text命名空间中包含众多编码的类,可供进行操作及转换。其中的Encoding类就是重点处理汉字编码的类。通过在.NET文档中查询Encoding类的方法我们可以发现所有和文字编码有关的都是字节数组,其中有两个很好用的方法:

Encoding.GetBytes ()方法将指定的 String 或字符数组的全部或部分内容编码为字节数组
Encoding.GetString ()方法将指定字节数组解码为字符串。


没错我们可以通过这两个方法将汉字字符编码为字节数组,同样知道了汉字GB2312的字节数组编码也就可以将字节数组解码为汉字字符。通过对“好”字进行编码为字节数组后

Encoding gb=System.Text.Encoding.GetEncoding("gb2312");
object[] bytes=gb.Encoding.GetBytes ("");


发现得到了一个长度为2的字节数组bytes,使用

string lowCode = System.Convert.ToString(bytes[0], 16); //取出元素1编码内容(两位16进制)
string hightCode = System.Convert.ToString(bytes[1], 16);//取出元素2编码内容(两位16进制)


之后发现字节数组bytes16进制变码后内容竟然是{ba,c3},刚好是“好”字的十六进制区位码(见区位码表)。
因此我们就可以随机生成一个长度为2的十六进制字节数组,使用GetString ()方法对其进行解码就可以得到汉字字符了。不过对于生成中文汉字验证码来说,因为第15区也就是AF区以前都没有汉字,只有少量符号,汉字都从第16区B0开始,并且从区位D7开始以后的汉字都是和很难见到的繁杂汉字,所以这些都要排出掉。所以随机生成的汉字十六进制区位码第1位范围在B、C、D之间,如果第1位是D的话,第2位区位码就不能是7以后的十六进制数。在来看看区位码表发现每区的第一个位置和最后一个位置都是空的,没有汉字,因此随机生成的区位码第3位如果是A的话,第4位就不能是0;第3位如果是F的话,第4位就不能是F。
好了,知道了原理,随机生成中文汉字的程序也就出来了,以下就是生成4个随机汉字的C#控制台代码:


3、程序代码:

using System;
using System.Text;

namespace ConsoleApplication
{
    
class ChineseCode
  
{
        
public static void Main()
        
{
            
//获取GB2312编码页(表)
            Encoding gb=Encoding.GetEncoding("gb2312");

            
//调用函数产生4个随机中文汉字编码
            object[] bytes=CreateRegionCode(4); 

            
//根据汉字编码的字节数组解码出中文汉字
            string str1=gb.GetString((byte[])Convert.ChangeType(bytes[0], typeof(byte[])));
            
string str2=gb.GetString((byte[])Convert.ChangeType(bytes[1], typeof(byte[])));
            
string str3=gb.GetString((byte[])Convert.ChangeType(bytes[2], typeof(byte[])));
            
string str4=gb.GetString((byte[])Convert.ChangeType(bytes[3], typeof(byte[])));

            
//输出的控制台
          Console.WriteLine(str1 + str2 +str3 +str4);
      }



        
/*
        此函数在汉字编码范围内随机创建含两个元素的十六进制字节数组,每个字节数组代表一个汉字,并将
        四个字节数组存储在object数组中。
        参数:strlength,代表需要产生的汉字个数
        
*/

        
public static object[] CreateRegionCode(int strlength)
        
{
            
//定义一个字符串数组储存汉字编码的组成元素
            string[] rBase=new String [16]{"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"};
            
            Random rnd
=new Random();
        
            
//定义一个object数组用来
            object[] bytes=new object[strlength];

            
/*每循环一次产生一个含两个元素的十六进制字节数组,并将其放入bject数组中
             每个汉字有四个区位码组成
             区位码第1位和区位码第2位作为字节数组第一个元素
             区位码第3位和区位码第4位作为字节数组第二个元素
            
*/

            
for(int i=0;i<strlength;i++)
            
{
                
//区位码第1位
                int r1=rnd.Next(11,14);
                
string str_r1=rBase[r1].Trim();

                
//区位码第2位
                rnd=new Random(r1*unchecked((int)DateTime.Now.Ticks)+i);//更换随机数发生器的

种子避免产生重复值
                
int r2;
                
if (r1==13)
                
{
                    r2
=rnd.Next(0,7);
                }

                
else
                
{
                    r2
=rnd.Next(0,16);
                }

                
string str_r2=rBase[r2].Trim();

                
//区位码第3位
                rnd=new Random(r2*unchecked((int)DateTime.Now.Ticks)+i);
                
int r3=rnd.Next(10,16);
                
string str_r3=rBase[r3].Trim();

                
//区位码第4位
                rnd=new Random(r3*unchecked((int)DateTime.Now.Ticks)+i);
                
int r4;
                
if (r3==10)
                
{
                    r4
=rnd.Next(1,16);
                }

                
else if (r3==15)
                
{
                    r4
=rnd.Next(0,15);
                }

                
else
                
{
                    r4
=rnd.Next(0,16);
                }

                
string str_r4=rBase[r4].Trim();

                
//定义两个字节变量存储产生的随机汉字区位码
                byte byte1=Convert.ToByte(str_r1 + str_r2,16);
                
byte byte2=Convert.ToByte(str_r3 + str_r4,16);
                
//将两个字节变量存储在字节数组中
                byte[] str_r=new byte[]{byte1,byte2};

                
//将产生的一个汉字的字节数组放入object数组中
                bytes.SetValue(str_r,i);
                
            }


            
return bytes;

            }

  }


}


实现了随机生成汉字后,就可以使用.NET GDI来绘制自己需要的验证码图形了。具体的怎样生成验证码图片,以及改变其中字符的长和宽等效果网上已经有很多相关的文章,这里由于篇幅就不再介绍了。不过有一点要说明的是以上代码在中文版的Windows下才能运行,因为它带有GB的字符集,如果你是其他语言的操作系统,就需要安装GB字符集了。

相关文章:

Rust 2020 调查报告出炉,95%的开发者吐槽Rust难学

来源 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;编译 | 苏宓头图 | CSDN 下载自东方 IC众多语言中&#xff0c;Rust 作为一款小众的现代系统编程语言&#xff0c;近几年间&#xff0c;接连受到了各大企业的青睐。正如不久前&#xff0c;AWS 开源团队宣布聘用 Rust …

Android中Parcel的分析和使用

http://www.360doc.com/content/13/0419/12/9171956_279433672.shtml

Kubernates集群入门(1)

一、K8s安装准备 1.至少两台主机&#xff0c;一台作为master&#xff0c;一台作为node。两台主机需要关闭防火墙。 #centos6 service stop firewalld && service disable firewalld #centos7 systemctl stop iptables && systemctl disable iptables; 2.两台…

Asp.net 不使用SQLDMO实现数据库备份和还原

今天需要做一个历史数据库,备份还原的程序,就是在sql服务器兴建一个数据库的历史版本的复.手工操作很方便,但是程序来实现我还没做过.上网找资料发现都调用了 SQLDMO 的 SQL COM 来实现. 应为我不想在应用服务器上面引用 COM 组件服务.所以没采取这种方式.打开Sql 联机帮助.发现…

B2B行业网站10种经营模式研究及组合方案

许多人对B2B网站的理解仅停留在企业对企业的在线交易上&#xff0c;认为按照B2B电子商务的概念就应该是在网上进行交易。但目前中国比较成功的B2B网站却并非所有都是在线交易模式&#xff0c;尤其是B2B行业网站&#xff0c;许多都没有做在线交易&#xff0c;更多是以基于交易为…

用户数年增长 300%,BitMax如何把握数字资产时代机遇?

12月22日&#xff0c;在2020 BitMax两周年庆典上&#xff0c;BitMax 创始人兼 CEO 曹晶、BitUniverse 合伙人许志宏、BlockVC 创始人徐英凯、红林集团&红链资本创始人李勇敏等多位区块链行业专家&#xff0c;分享了行业洞察&#xff0c;一同探讨交易所的现状和突围之战、数…

2014 年美国程序员薪资调查

Drdobbs 近期向 2,200 名美国的程序开发人员做了一次调查&#xff0c;调查显示高薪领域的工资随着经济的增长而增长。 “Software Engineer”这个职位&#xff0c;除了在德州和几个其他州之外&#xff0c;没有什么特别的意思&#xff0c;在这几个州用这个职称需要经过评定。在其…

ASP.net 验证码(C#)

ASP.net 验证码(C#) /* Copyright all(c) 2005 ZhongFeng, http://blog.csdn.net/SW515 */ public class ValidateCode : System.Web.UI.Page { private void Page_Load(object sender, System.EventArgs e) { this.CreateCheckCodeImage(GenerateCheckCode()); } #region…

SCCM 2012 SP1系列(十)配置补丁更新-3

自动部署规则SCCM2012中对补丁分发增加了一项新功能—自动部署规则&#xff0c;这功能相当于WSUS的自动审批功能。就是当检测到新的补丁更新后自动进行下载更新动作&#xff0c;然后下发给客户端。其实在大企业中还是建议会对每个更新包进行测试&#xff0c;确定对现有业务没有…

CSDN湘苗培优|保持热情,告别平庸

湘苗培优招生进行中在培优中&#xff0c;遇见更好的自己——CSDN高校俱乐部CSDN湘苗培优随着我国信息产业飞速发展&#xff0c;通过常规灌输式培养出来的学员已经不能够满足企业要求。企业更缺乏的是具备自主学习能力、具备综合解决问题能力的高素质技术人才。高素质技术人才需…

在c#中调用windows脚本的方法

在c#中调用windows脚本的方法 方法1&#xff1a;直接调用CODE: System.Diagnostics.Process proc new System.Diagnostics.Process();proc.StartInfo.FileName"wscript";proc.StartInfo.Arguments" hello.js"; proc.StartInfo.UseShellExecute false;pr…

ie和firefox操作table对象的异同

2019独角兽企业重金招聘Python工程师标准>>> ie和firefox下操作table对象的异同【测试浏览器版本&#xff1a;ie为8,9&#xff0c;firefox为2.0】 1&#xff09;在ie下&#xff0c;table标签直接使用appendChild增加document.createElement(tr)的行时不显示&#xf…

机器学习和计算机视觉的前20个图像数据集

作者 | Meiryum Ali 翻译 | 火火酱,责编 | 晋兆雨出品 | AI科技大本营头图 | 付费下载于视觉中国计算机视觉使计算机能够理解图像和视频的内容。计算机视觉的目标是使人类视觉系统可以实现任务自动化。计算机视觉任务包括图像采集、图像处理和图像分析。图像数据可以采用不同的…

移动应用开发者应该关注的 Google I/O 两项更新

移动应用开发者看过来&#xff0c;今年 Google I/O 这两项更新能帮上大忙移动应用开发者看过来&#xff0c;今年 Google I/O 这两项更新能帮上大忙。 I/O 的 Keynote 刚刚结束&#xff0c;用户可能为 Google 新的消费产品感到兴奋。但这毕竟是开发者大会&#xff0c;一些面向开…

赠书 | 手把手教你自己动手打造一个智能恒温器

作者 | Yazeed Sabri翻译 | 火火酱,责编 | 晋兆雨出品 | AI科技大本营头图 | 付费下载于视觉中国*文末有赠书福利为了能住得离公司近一点&#xff0c;我就搬进了一套没有温控系统的公寓。因为在芝加哥市区&#xff0c;这个价位的公寓大多都是没有温控系统的&#xff0c;所以我心…

JVM 出了问题 EXCEPTION_ACCESS_VIOLATION

2019独角兽企业重金招聘Python工程师标准>>> # # An unexpected error has been detected by Java Runtime Environment: # # EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc0x10002c08, pid5972, tid1404 # # Java VM: Java HotSpot(TM) Client VM (11.3-b02 mixe…

转换字符串中汉字为其拼音缩写(C#)

//将指定字符串中的汉字转换为拼音缩写&#xff0c;其中非汉字保留为原字符。 public string GetPinYin( string text){char pinyin;byte[] array;System.Text.StringBuilder sb new System.Text.StringBuilder(text.Length); foreach(char c in text) { pinyin c; …

weblogic线程阻塞性能调优(图解)

转自&#xff1a;http://blog.csdn.net/z69183787/article/details/12647539 声明&#xff1a;出现这个问题有程序方面、网络方面、weblogic设置方面等等原因&#xff0c;此文章主要讲述由于weblogic设置而导致的解决办法。 因为&#xff1a; 1.程序问题&#xff0c;需要项目自…

ASP.net实现无扩展名的URL重写。简单、方便、无需ISAPI

URL重写已经有很多的方法&#xff0c;但是多数都有一个缺点&#xff0c;就是不支持无扩展名的网页。微软提供的方法需要在根目录里面建立jyk的文件夹&#xff0c;然后再建立一个default.aspx的文件&#xff0c;如果您有100名会员的话&#xff0c;这是一个不可想象的事情。 另一…

IDC公布中国深度学习市场综合份额:百度超越Facebook位列第二

近日&#xff0c;权威数据调研机构IDC公布了2020年下半年深度学习框架平台市场份额报告。数据显示&#xff0c;在中国深度学习平台市场综合份额中&#xff0c;Google、百度、Facebook稳居前三&#xff0c;占据70%以上市场份额。其中&#xff0c;百度占比提升3.38%增速第一&…

OpenStack 和 Cloud Foundry

上周我参加了在亚特兰大举行的OpenStack峰会&#xff0c;这是一个非常好的机会去进一步了解Cloud Foundry 和OpenStack ecosystem之间的关系。 在OpenStack阵营里&#xff0c;在讨论PaaS时&#xff0c;“Could Foundry 是不是 OpenStack” &#xff0c;这个看起来像是一个有争议…

防止IIS文件被下载方法

如何才能防止encry目录下的所有文件被非法下载呢&#xff1f;我们可以应用IIS中的应用程序映射结合ASP.NET中的IHttpHandler自定义权限&#xff0c;把IIS应用程序映射用于所有文件&#xff0c;并将控制权交给我们自己实现的IHttpHandler。 首先添加应用程序映射&#xff1a;打…

转 如何在IOS设备中去掉屏幕上的status bar

引入如何在IOS设备中去掉屏幕上的status bar&#xff0c;即&#xff1a;不显示设备上方的&#xff3b;网络、时间、电池??&#xff3d;条&#xff1f;操作方法一&#xff1a;在-info.list项目文件中&#xff0c;加上“Status bar is initially hidden”选项&#xff0c;并勾选…

倒计时7天!博客之星虚位以待,Macbook等你来拿

也许你陪伴了CSDN一年的时间刚刚写下自己的第二十篇的原创技术博文也许你是陪伴了CSDN近20年风雨的老码农更新了近千百篇的技术文章也许你还在坚持着“技术输出”也许你已经开始封笔也许你刚刚突破粉丝数达到了三位&#xff0c;四位数也许你刚刚申请的博客专家&#xff0c;终于…

UVA 10515 - Powers Et Al.(数论)

UVA 10515 - Powers Et Al. 题目链接 题意&#xff1a;求出m^n最后一位数 思路&#xff1a;因为m和n都非常大&#xff0c;直接算肯定是不行的&#xff0c;非常easy想到取最后一位来算&#xff0c;然后又非常easy想到最后一位不断乘自身肯定会形成周期。而且这个周期还挺短的&am…

视觉+Transformer最新论文出炉,华为联合北大、悉尼大学发表

作者 | CV君来源 | 我爱计算机视觉Transformer 技术最开始起源于自然语言处理领域&#xff0c;但今年5月份Facebook 的一篇文章将其应用于计算机视觉中的目标检测(DETR算法&#xff0c;目前已有78次引用)使其大放异彩&#xff0c;并迅速得到CV研究社区的关注。已有研究表明&…

易宝典文章——怎样管理Exchange Server 2013邮箱地址

对于一个用户邮箱&#xff0c;即邮箱收件人来讲&#xff0c;在创建时Exchange会为其按照Alias分配一个邮件地址&#xff0c;即主邮件地址&#xff0c;也称为“主SMTP地址”或“默认答复地址”。但是在用户日常使用中可能会出现需要多个邮件地址的情况&#xff0c;比如&#xff…

使用FileUpload控件上传图片并自动生成缩略图、自动生成带文字和图片的水印图

本文借助vs2005中自带的FileUpload控件实现图片文件的上传并生成缩略图。实现过程&#xff1a;选择图片上传成功后&#xff0c;取得已经存在服务器的文件生成缩略图&#xff0c;并且判断是否是图片类型的文件&#xff0c;这个的判断可以在程序中修改&#xff0c;本程序只是判断…

Java -- JDBC 学习--通过Statement进行数据库更新操作

通过 JDBC 向指定的数据表中插入一条记录. 1. Statement: 用于执行 SQL 语句的对象 1). 通过 Connection 的 createStatement() 方法来获取 2). 通过 executeUpdate(sql) 可以执行 SQL 语句. 3). 传入的 SQL 可以是 INSRET, UPDATE 或 DELETE. 但不能是 SELECT 2.…

身份证号码验证-支持新的带x身份证

//--身份证号码验证-支持新的带x身份证functionisIdCardNo(num) { varfactorArr newArray(7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2,1); varerror; varvarArray newArray(); varintValue; varlngProduct 0; varintCheckDigit; varintStrLen num.length; v…