I need a unique identifier in .NET (cannot use GUID as it is too long for this case).
Do people think that the algorithm used here is a good candidate or do you have any other suggestions?
This one a good one - http://www.singular.co.nz/blog/archive/2007/12/20/shortguid-a-shorter-and-url-friendly-guid-in-c-sharp.aspx
and also here YouTube-like GUID
You could use Base64:
string base64Guid = Convert.ToBase64String(Guid.NewGuid().ToByteArray());
That generates a string like E1HKfn68Pkms5zsZsvKONw==. Since a GUID is always 128 bits, you can omit the == that you know will always be present at the end and that will give you a 22 character string. This isn't as short as YouTube though.
I use a similar approach as Dor Cohen's but removing some special characters:
var uid = Regex.Replace(Convert.ToBase64String(Guid.NewGuid().ToByteArray()), "[/+=]", "");
This will output just alphanumeric characters. The UIDs are not guaranteed to have always the same length. Here is a sample run:
vmKo0zws8k28fR4V4Hgmw
TKbhS0G2V0KqtpHOU8e6Ug
rfDi1RdO0aQHTosh9dVvw
3jhCD75fUWjQek8XRmMg
CQUg1lXIXkWG8KDFy7z6Ow
bvyxW5aj10OmKA5KMhppw
pIMK8eq5kyvLK67xtsIDg
VX4oljGWpkSQGR2OvGoOQ
NOHBjUUHv06yIc7EvotRg
iMniAuUG9kiGLwBtBQByfg
Simple usable package. I use it for temporal request id generator.
https://www.nuget.org/packages/shortid
https://github.com/bolorundurowb/shortid
Uses System.Random
string id = ShortId.Generate();
// id = KXTR_VzGVUoOY
(from the github page)
If you want to control the type of id generated by specifying whether you want numbers, special characters and the length, call the Generate method and pass three parameters, the first a boolean stating whether you want numbers, the second a boolean stating whether you want special characters, the last a number indicating your length preference.
string id = ShortId.Generate(true, false, 12);
// id = VvoCDPazES_w
var ticks = new DateTime(2016,1,1).Ticks;
var ans = DateTime.Now.Ticks - ticks;
var uniqueId = ans.ToString("x");
Keep a baseline date (which in this case is 1st Jan 2016) from when you will start generating these ids. This will make your ids smaller.
Generated Number: 3af3c14996e54
As far as I know, just stripping off a part of a GUID isn't guaranteed to be unique - in fact, it's far from being unique.
The shortest thing that I know that guarantees global uniqueness is featured in this blog post by Jeff Atwood. In the linked post, he discusses multiple ways to shorten a GUID, and in the end gets it down to 20 bytes via Ascii85 encoding.
However, if you absolutely need a solution that's no longer than 15 bytes, I'm afraid you have no other choice than to use something which is not guaranteed to be globally unique.
IDENTITY values should be unique in a database, but you should be aware of the limitations... for example, it makes bulk data inserts basically impossible which will slow you down if you're working with a very large number of records.
You may also be able to use a date/time value. I've seen several databases where they use the date/time to be the PK, and while it's not super clean - it works. If you control the inserts, you can effectively guarantee that the values will be unique in code.
For my local app I'm using this time based approach:
/// <summary>
/// Returns all ticks, milliseconds or seconds since 1970.
///
/// 1 tick = 100 nanoseconds
///
/// Samples:
///
/// Return unit value decimal length value hex length
/// --------------------------------------------------------------------------
/// ticks 14094017407993061 17 3212786FA068F0 14
/// milliseconds 1409397614940 13 148271D0BC5 11
/// seconds 1409397492 10 5401D2AE 8
///
/// </summary>
public static string TickIdGet(bool getSecondsNotTicks, bool getMillisecondsNotTicks, bool getHexValue)
{
string id = string.Empty;
DateTime historicalDate = new DateTime(1970, 1, 1, 0, 0, 0);
if (getSecondsNotTicks || getMillisecondsNotTicks)
{
TimeSpan spanTillNow = DateTime.UtcNow.Subtract(historicalDate);
if (getSecondsNotTicks)
id = String.Format("{0:0}", spanTillNow.TotalSeconds);
else
id = String.Format("{0:0}", spanTillNow.TotalMilliseconds);
}
else
{
long ticksTillNow = DateTime.UtcNow.Ticks - historicalDate.Ticks;
id = ticksTillNow.ToString();
}
if (getHexValue)
id = long.Parse(id).ToString("X");
return id;
}
If your app dont have a few MILLIION people, using that generate short unique string at the SAME MILLISECOND, you can think about using below function.
private static readonly Object obj = new Object();
private static readonly Random random = new Random();
private string CreateShortUniqueString()
{
string strDate = DateTime.Now.ToString("yyyyMMddhhmmssfff");
string randomString ;
lock (obj)
{
randomString = RandomString(3);
}
return strDate + randomString; // 16 charater
}
private string RandomString(int length)
{
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxy";
var random = new Random();
return new string(Enumerable.Repeat(chars, length)
.Select(s => s[random.Next(s.Length)]).ToArray());
}
change yyyy to yy if you just need to use your app in next 99 year.
Update 20160511: Correct Random function
- Add Lock object
- Move random variable out of RandomString function
Ref
here my solution, is not safe for concurrency, no more of 1000 GUID's per seconds and thread safe.
public static class Extensors
{
private static object _lockGuidObject;
public static string GetGuid()
{
if (_lockGuidObject == null)
_lockGuidObject = new object();
lock (_lockGuidObject)
{
Thread.Sleep(1);
var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
var epochLong = Convert.ToInt64((DateTime.UtcNow - epoch).TotalMilliseconds);
return epochLong.DecimalToArbitrarySystem(36);
}
}
/// <summary>
/// Converts the given decimal number to the numeral system with the
/// specified radix (in the range [2, 36]).
/// </summary>
/// <param name="decimalNumber">The number to convert.</param>
/// <param name="radix">The radix of the destination numeral system (in the range [2, 36]).</param>
/// <returns></returns>
public static string DecimalToArbitrarySystem(this long decimalNumber, int radix)
{
const int BitsInLong = 64;
const string Digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
if (radix < 2 || radix > Digits.Length)
throw new ArgumentException("The radix must be >= 2 and <= " + Digits.Length.ToString());
if (decimalNumber == 0)
return "0";
int index = BitsInLong - 1;
long currentNumber = Math.Abs(decimalNumber);
char[] charArray = new char[BitsInLong];
while (currentNumber != 0)
{
int remainder = (int)(currentNumber % radix);
charArray[index--] = Digits[remainder];
currentNumber = currentNumber / radix;
}
string result = new String(charArray, index + 1, BitsInLong - index - 1);
if (decimalNumber < 0)
{
result = "-" + result;
}
return result;
}
code not optimized, just sample!.
I know it's quite far from posted date... :)
I have a generator which produces only 9 Hexa characters, eg: C9D6F7FF3, C9D6FB52C
public class SlimHexIdGenerator : IIdGenerator
{
private readonly DateTime _baseDate = new DateTime(2016, 1, 1);
private readonly IDictionary<long, IList<long>> _cache = new Dictionary<long, IList<long>>();
public string NewId()
{
var now = DateTime.Now.ToString("HHmmssfff");
var daysDiff = (DateTime.Today - _baseDate).Days;
var current = long.Parse(string.Format("{0}{1}", daysDiff, now));
return IdGeneratorHelper.NewId(_cache, current);
}
}
static class IdGeneratorHelper
{
public static string NewId(IDictionary<long, IList<long>> cache, long current)
{
if (cache.Any() && cache.Keys.Max() < current)
{
cache.Clear();
}
if (!cache.Any())
{
cache.Add(current, new List<long>());
}
string secondPart;
if (cache[current].Any())
{
var maxValue = cache[current].Max();
cache[current].Add(maxValue + 1);
secondPart = maxValue.ToString(CultureInfo.InvariantCulture);
}
else
{
cache[current].Add(0);
secondPart = string.Empty;
}
var nextValueFormatted = string.Format("{0}{1}", current, secondPart);
return UInt64.Parse(nextValueFormatted).ToString("X");
}
}
Based on @dorcohen's answer and @pootzko's comment. You can use this. It is safe over the wire.
var errorId = System.Web.HttpServerUtility.UrlTokenEncode(Guid.NewGuid().ToByteArray());
I use the following to create an unique guid(35 characters).
// Example: 7b08e3d-186b-46f0-99c8-e8252033715d
var strUniqueGuid = Guid.NewGuid().ToString();
If you like a unique guid with 16 characters, please use the below code
// Example: 7b08e3d-186b-46f
var strUniqueGuid = Guid.NewGuid().ToString();
strUniqueGuid=strUniqueGuid.Substring(0, 16);
If you dont need to type the string you could use the following:
static class GuidConverter
{
public static string GuidToString(Guid g)
{
var bytes = g.ToByteArray();
var sb = new StringBuilder();
for (var j = 0; j < bytes.Length; j++)
{
var c = BitConverter.ToChar(bytes, j);
sb.Append(c);
j++;
}
return sb.ToString();
}
public static Guid StringToGuid(string s)
=> new Guid(s.SelectMany(BitConverter.GetBytes).ToArray());
}
This will convert the Guid to a 8 character String like this:
{b77a49a5-182b-42fa-83a9-824ebd6ab58d} --> "䦥띺ᠫ䋺ꦃ亂檽趵"
{c5f8f7f5-8a7c-4511-b667-8ad36b446617} --> "엸詼䔑架펊䑫ᝦ"
you can use
code = await UserManager.GenerateChangePhoneNumberTokenAsync(input.UserId, input.MobileNumber);
its 6
nice characters only, 599527
,143354
and when user virify it simply
var result = await UserManager.VerifyChangePhoneNumberTokenAsync(input.UserId, input.Token, input.MobileNumber);
hope this help you
I use Guid.NewGuid().ToString().Split('-')[0]
, it gets the first item from the array separated by the '-'. Its enough to represent a unique key.
Guid.NewGuid().ToString().Split('-').First()
来源:https://stackoverflow.com/questions/9278909/net-short-unique-identifier