Can someone point me to the preferred method for generating a report or document ID? I have been looking at maybe using a guid that would be reduced down to a shorter length. We have an application that creates an ID for reports that is about 8 characters long. They appear to be using some type of hash code. Probably using a base 36 encoding scheme. But I cant seem to find a way to make the hash code come out to a length of 8 characters since people have to use them to refer to the documents. They would also be used in a disconnected environment, so you couldnt look up the next usable serialized number in the chain. Just wondering what some of you use in applications like this?
2 回答
The .net Framwork provides RNGCryptoServiceProvider class which Implements a cryptographic Random Number Generator (RNG) using the implementation provided by the cryptographic service provider (CSP). This class is usually used to generate random numbers. Although I can use this class to generate unique number in some sense but it is also not collision less. Moreover while generating key we can make key more complicated by making it as alpha numeric rather than numeric only. So, I used this class along with some character masking to generate unique key of fixed length.
private string GetUniqueKey()
{
int maxSize = 8 ;
int minSize = 5 ;
char[] chars = new char[62];
string a;
a = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
chars = a.ToCharArray();
int size = maxSize ;
byte[] data = new byte[1];
RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider();
crypto.GetNonZeroBytes(data) ;
size = maxSize ;
data = new byte[size];
crypto.GetNonZeroBytes(data);
StringBuilder result = new StringBuilder(size) ;
foreach(byte b in data )
{ result.Append(chars[__b % (chars.Length - )>); }
<span class="code-keyword">return result.ToString();
}
http://www.codeproject.com/Articles/14403/Generating-Unique-Keys-in-Net
This is what I ended up using. It is a base36 encoding. I borrowed parts of the code from other people, so I cant claim that I wrote it all, but I hope this helps others. This will produce about a 12 digit record ID, or unique ID for databases etc. It uses only the last 2 digits of the year, so it should be good for 100 years.
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace Base36Converter
{
public partial class Form1 : Form
{
private const string CharList = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public Form1()
{
InitializeComponent();
}
//Base 36 number consists of only numbers and uppercase letters only.
private void button1_Click(object sender, EventArgs e)
{
if (textBox2.Text.Length > 0)
{
label3.Text = "";
//Get Date and Time Stamp
string temp1 = GetTimestamp(DateTime.Now);
//Turn it into a long number
long l = Convert.ToInt64(temp1);
//Now encode it as a base36 number.
string s1 = Encode(l);
//Get userID as a number, i.e. 1055 (User's index number) and create as a long type.
long l1 = Convert.ToInt64(textBox2.Text);
//Encode it as a base36 number.
string s2 = Encode(l1);
//Now display it as the encoded user number + datetime encoded number (Concatenated)
textBox1.Text = s2 + s1;
}
else
{
label3.Text = "User Number must be greater than 0. ie 1055";
}
}
public static String Encode(long input)
{
if (input < 0) throw new ArgumentOutOfRangeException("input", input, "input cannot be negative");
char[] clistarr = CharList.ToCharArray();
var result = new Stack<char>();
while (input != 0)
{
result.Push(clistarr[input % 36]);
input /= 36;
}
return new string(result.ToArray());
}
public static String GetTimestamp(DateTime value)
{
return value.ToString("yyMMddHHmmssffff");
}
private void Form1_Load(object sender, EventArgs e)
{
label3.Text = "";
}
}
}