zl程序教程

您现在的位置是:首页 >  后端

当前栏目

C#生成唯一值的方法汇总

c#方法 生成 汇总 唯一
2023-06-13 09:15:13 时间

生成唯一值的方法很多,下面就不同环境下生成的唯一标识方法一一介绍,作为工作中的一次总结,有兴趣的可以自行测试:

一、在.NET中生成

1、直接用.NETFramework提供的Guid()函数,此种方法使用非常广泛。GUID(全局统一标识符)是指在一台机器上生成的数字,它保证对在同一时空中的任何两台计算机都不会生成重复的GUID值(即保证所有机器都是唯一的)。关于GUID的介绍在此不作具体熬述,想深入了解可以自行查阅MSDN。代码如下:

复制代码代码如下:

usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;

namespaceConsoleApplication1
{
   classProgram
   {
       staticvoidMain(string[]args)
       {
           string_guid=GetGuid();
           Console.WriteLine("唯一码:{0}\t长度为:{1}\n去掉连接符:{2}",_guid,_guid.Length,_guid.Replace("-",""));

           stringuniqueIdString=GuidTo16String();
           Console.WriteLine("唯一码:{0}\t长度为:{1}",uniqueIdString,uniqueIdString.Length);

           longuniqueIdLong=GuidToLongID();
           Console.WriteLine("唯一码:{0}\t长度为:{1}",uniqueIdLong,uniqueIdLong.ToString().Length);

       }

       ///<summary>
       ///由连字符分隔的32位数字
       ///</summary>
       ///<returns></returns>
       privatestaticstringGetGuid()
       {
           System.Guidguid=newGuid();
           guid=Guid.NewGuid();
           returnguid.ToString();
       }

       ///<summary> 
       ///根据GUID获取16位的唯一字符串 
       ///</summary> 
       ///<paramname=\"guid\"></param> 
       ///<returns></returns> 
       publicstaticstringGuidTo16String()
       {
           longi=1;
           foreach(bytebinGuid.NewGuid().ToByteArray())
               i*=((int)b+1);

           returnstring.Format("{0:x}",i-DateTime.Now.Ticks);
       }

       ///<summary> 
       ///根据GUID获取19位的唯一数字序列 
       ///</summary> 
       ///<returns></returns> 
       publicstaticlongGuidToLongID()
       {
           byte[]buffer=Guid.NewGuid().ToByteArray();
           returnBitConverter.ToInt64(buffer,0);
       }  

   }
}

2、用DateTime.Now.ToString("yyyyMMddHHmmssms")和.NETFramework提供的RNGCryptoServiceProvider()结合生成,代码如下:

复制代码代码如下:

usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;

usingSystem.Threading;

namespaceConsoleApplication1
{
   classProgram
   {
       staticvoidMain(string[]args)
       {
           stringuniqueNum=GenerateOrderNumber();
           Console.WriteLine("唯一码:{0}\t长度为:{1}",uniqueNum,uniqueNum.Length);

           //测试是否会生成重复
             Console.WriteLine("时间+RNGCryptoServiceProvider()结合生成的唯一值,如下:");
           string_tempNum=string.Empty;
           for(inti=0;i<1000;i++)
           {
               stringuNum=GenerateOrderNumber();
               Console.WriteLine(uNum);
               if(string.Equals(uNum,_tempNum))
               {
                   Console.WriteLine("上值存在重复,按Enter键继续");
                   Console.ReadKey();
               }

               //Sleep当前线程,是为了延时,从而不产生重复值。可以把它注释掉测试看
               Thread.Sleep(300);

               _tempNum=uNum;
           }

       }

       ///<summary>
       ///唯一订单号生成
       ///</summary>
       ///<returns></returns>
       publicstaticstringGenerateOrderNumber()
       {
           stringstrDateTimeNumber=DateTime.Now.ToString("yyyyMMddHHmmssms");
           stringstrRandomResult=NextRandom(1000,1).ToString();

           returnstrDateTimeNumber+strRandomResult;
       }

       ///<summary>
       ///参考:msdn上的RNGCryptoServiceProvider例子
       ///</summary>
       ///<paramname="numSeeds"></param>
       ///<paramname="length"></param>
       ///<returns></returns>
       privatestaticintNextRandom(intnumSeeds,intlength)
       {
           //Createabytearraytoholdtherandomvalue. 
           byte[]randomNumber=newbyte[length];
           //CreateanewinstanceoftheRNGCryptoServiceProvider. 
           System.Security.Cryptography.RNGCryptoServiceProviderrng=newSystem.Security.Cryptography.RNGCryptoServiceProvider();
           //Fillthearraywitharandomvalue. 
           rng.GetBytes(randomNumber);
           //Convertthebytetoanuintvaluetomakethemodulusoperationeasier. 
           uintrandomResult=0x0;
           for(inti=0;i<length;i++)
           {
               randomResult|=((uint)randomNumber[i]<<((length-1-i)*8));
           }

           return(int)(randomResult%numSeeds)+1;
       }
   }
}

3、用[0-9A-Z]+Guid.NewGuid()结合生成特定位数的唯一字符串,代码如下:

复制代码代码如下:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;

namespaceConsoleApplication1
{
   classProgram
   {
       staticvoidMain(string[]args)
       {
           stringuniqueText=GenerateUniqueText(8);
           Console.WriteLine("唯一码:{0}\t长度为:{1}",uniqueText,uniqueText.Length);

           //测试是否会生成重复
             Console.WriteLine("由[0-9A-Z]+NewGuid()结合生成的唯一值,如下:");
           IList<string>list=newList<string>();
           for(inti=1;i<=1000;i++)
           {
               string_uT=GenerateUniqueText(8);
               Console.WriteLine("{0}\t{1}",list.Count,_uT);
               if(list.Contains(_uT))
               {
                   Console.WriteLine("{0}值存在重复",_uT);
                   Console.ReadKey();
               }

               list.Add(_uT);

               //if(i%200==0)
               //{
                   //Console.WriteLine("没有重复,按Enter键往下看");
                   //Console.ReadKey();
               //}
           }

           list.Clear();
       }

       ///<summary>
       ///生成特定位数的唯一字符串
       ///</summary>
       ///<paramname="num">特定位数</param>
       ///<returns></returns>
       publicstaticstringGenerateUniqueText(intnum)
       {
           stringrandomResult=string.Empty;
           stringreadyStr="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
           char[]rtn=newchar[num];
           Guidgid=Guid.NewGuid();
           varba=gid.ToByteArray();
           for(vari=0;i<num;i++)
           {
               rtn[i]=readyStr[((ba[i]+ba[num+i])%35)];
           }

           foreach(charrinrtn)
           {
               randomResult+=r;
           }

           returnrandomResult;
       }

   }
}

4、用单例模式实现,由[0-9a-z]组合生成的唯一值,此文不讨论单例模式的多种实现方式与性能问题,随便弄一种方式实现,代码如下:

Demo结构如图:

Program.cs程序:

复制代码代码如下:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;

usingSystem.Collections;
usingSystem.Xml;

namespaceConsoleApplication4
{
   classProgram
   {
       staticvoidMain(string[]args)
       {
           CreateIDcreateID=CreateID.GetInstance();

           //测试是否会生成重复
           Console.WriteLine("单例模式实现,由[0-9a-z]组合生成的唯一值,如下:");
           IList<string>list=newList<string>();
           for(inti=1;i<=1000000000;i++)
           {
               stringstrUniqueNum=createID.CreateUniqueID();
               Console.WriteLine("{0}\t{1}",list.Count,strUniqueNum);
               if(list.Contains(strUniqueNum))
               {
                   Console.WriteLine("{0}值存在重复",strUniqueNum);
                   Console.ReadKey();
               }

               list.Add(strUniqueNum);

               if(i%200==0)
               {
                   Console.WriteLine("没有重复,按Enter键往下看");
                   Console.ReadKey();
               }
           }

           list.Clear();
       }
   }

   ///<summary>
   ///单例模式实现
   ///唯一值由[0-9a-z]组合而成,且生成的每个ID不能重复
   ///</summary>
   publicclassCreateID
   {
       privatestaticCreateID_instance;
       privatestaticreadonlyobjectsyncRoot=newobject();
       privateEHashtablehashtable=newEHashtable();
       privatestring_strXMLURL=string.Empty;

       privateCreateID()
       {
           hashtable.Add("0","0");
           hashtable.Add("1","1");
           hashtable.Add("2","2");
           hashtable.Add("3","3");
           hashtable.Add("4","4");
           hashtable.Add("5","5");
           hashtable.Add("6","6");
           hashtable.Add("7","7");
           hashtable.Add("8","8");
           hashtable.Add("9","9");
           hashtable.Add("10","a");
           hashtable.Add("11","b");
           hashtable.Add("12","c");
           hashtable.Add("13","d");
           hashtable.Add("14","e");
           hashtable.Add("15","f");
           hashtable.Add("16","g");
           hashtable.Add("17","h");
           hashtable.Add("18","i");
           hashtable.Add("19","j");
           hashtable.Add("20","k");
           hashtable.Add("21","l");
           hashtable.Add("22","m");
           hashtable.Add("23","n");
           hashtable.Add("24","o");
           hashtable.Add("25","p");
           hashtable.Add("26","q");
           hashtable.Add("27","r");
           hashtable.Add("28","s");
           hashtable.Add("29","t");
           hashtable.Add("30","u");
           hashtable.Add("31","v");
           hashtable.Add("32","w");
           hashtable.Add("33","x");
           hashtable.Add("34","y");
           hashtable.Add("35","z");
           _strXMLURL=System.IO.Path.GetFullPath(@"..\..\")+"XMLs\\record.xml";

       }

       publicstaticCreateIDGetInstance()
       {
           if(_instance==null)
           {
               lock(syncRoot)
               {
                   if(_instance==null)
                   {
                       _instance=newCreateID();
                   }
               }
           }

           return_instance;
       }

       ///<summary>
       ///创建UniqueID
       ///</summary>
       ///<returns>UniqueID</returns>
       publicstringCreateUniqueID()
       {
           long_uniqueid=GetGuidFromXml();

           returnConvert10To36(_uniqueid);
       }

       ///<summary>
       ///获取UniqueID总记录,即获取得到的这个ID是第几个ID
       ///更新UniqueID使用的个数,用于下次使用
       ///</summary>
       ///<returns></returns>
       privatelongGetGuidFromXml()
       {
           longrecord=0;
           XmlDocumentxmldoc=newXmlDocument();
           xmldoc.Load(_strXMLURL);
           XmlElementrootNode=xmldoc.DocumentElement;
           //此次的个数值
           record=Convert.ToInt64(rootNode["record"].InnerText);
           //此次的个数值+1==下次的个数值
           rootNode["record"].InnerText=Convert.ToString(record+1);
           xmldoc.Save(_strXMLURL);

           returnrecord;
       }

       ///<summary>
       ///10进制转36进制
       ///</summary>
       ///<paramname="intNum10">10进制数</param>
       ///<returns></returns>
       privatestringConvert10To36(longintNum10)
       {
           stringstrNum36=string.Empty;
           longresult=intNum10/36;
           longremain=intNum10%36;
           if(hashtable.ContainsKey(remain.ToString()))
               strNum36=hashtable[remain.ToString()].ToString()+strNum36;
           intNum10=result;
           while(intNum10/36!=0)
           {
               result=intNum10/36;
               remain=intNum10%36;
               if(hashtable.ContainsKey(remain.ToString()))
                   strNum36=hashtable[remain.ToString()].ToString()+strNum36;
               intNum10=result;
           }
           if(intNum10>0&&intNum10<36)
           {
               if(hashtable.ContainsKey(intNum10.ToString()))
                   strNum36=hashtable[intNum10.ToString()].ToString()+strNum36;
           }

           returnstrNum36;
       }

   }

   ///<summary>
   ///SummarydescriptionforEHashTable
   ///</summary>
   publicclassEHashtable:Hashtable
   {
       privateArrayListlist=newArrayList();
       publicoverridevoidAdd(objectkey,objectvalue)
       {
           base.Add(key,value);
           list.Add(key);
       }
       publicoverridevoidClear()
       {
           base.Clear();
           list.Clear();
       }
       publicoverridevoidRemove(objectkey)
       {
           base.Remove(key);
           list.Remove(key);
       }
       publicoverrideICollectionKeys
       {
           get
           {
               returnlist;
           }
       }
   }

}

XML:

复制代码代码如下:
<?xmlversion="1.0"encoding="utf-8"?>
<root>
 <recordid="record">1</record>
</root>

二、在JS中生成GUID,类似.NET中的Guid.NewGuid(),代码如下:

复制代码代码如下:
functionnewGuid(){//方法一:
   varguid="";
   varn=(((1+Math.random())*0x10000)|0).toString(16).substring(1);
   for(vari=1;i<=8;i++){
       guid+=n;
   }
   returnguid;
}

functionnewGuid(){//方法二:
   varguid="";
   for(vari=1;i<=32;i++){
       varn=Math.floor(Math.random()*16.0).toString(16);
       guid+=n;
       if((i==8)||(i==12)||(i==16)||(i==20))
           guid+="-";
   }
   returnguid;
}

三、在SQL存储过程生成GUID,代码如下:

复制代码代码如下:
--=============================================
--Author:     JBen
--Createdate:2012-06-05
--Description:生成唯一标识ID,公共存储过程,可设置在别的存储过程调用此存储过程传不同的前缀
--=============================================
ALTERPROCEDURE[dbo].[pro_CreateGuid]
   @PrefixNVARCHAR(10),
   @outputV_guidNVARCHAR(40)OUTPUT
AS
BEGIN
   --SETNOCOUNTONaddedtopreventextraresultsetsfrom
   --interferingwithSELECTstatements.
   SETNOCOUNTON;

   --Insertstatementsforprocedurehere
   SET@outputV_guid=@Prefix+REPLACE(CAST(NEWID()ASVARCHAR(36)),"-","")
END