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
public static string ToTinyUuid(this Guid guid)
{
return Convert.ToBase64String(guid.ToByteArray())[0..^2] // remove trailing == padding
.Replace('+', '-') // escape (for filepath)
.Replace('/', '_'); // escape (for filepath)
}
Usage
Guid.NewGuid().ToTinyUuid()
It's not rocket science to convert back, so I'll leave you that much.
private static readonly object _getUniqueIdLock = new object();
public static string GetUniqueId()
{
lock(_getUniqueIdLock)
{
System.Threading.Thread.Sleep(1);
return DateTime.UtcNow.Ticks.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());
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} --> "엸詼䔑架펊䑫ᝦ"
22 chars, url safe, and retains Guid uniqueness.
// Our url safe, base 64 alphabet:
const string alphabet = "-_0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
// Sanitized Guid string. Preserve the last two hex chars
var guidStr = "929F7C4D4B2644E1A122A379C02D6345";
var lastTwo = guidStr.Substring(30, 2);
string shortGuid = "";
// Iterate over the ten groups of 3 hex chars: 929 F7C 4D4 B26 44E 1A1 22A 379 C02 D63
for (var i = 0; i < 10; i++)
{
var hex = guidStr.Substring(i*3, 3); // Get the next 3 hex chars
var x = Convert.ToInt32(hex, 16); // Convert to int
shortGuid += $"{alphabet[x/64]}{alphabet[x%64]}"; // Lookup the two-digit base64 value
}
shortGuid += lastTwo; // Don't forget the last two
Console.WriteLine(shortGuid);
Output:
yDXWhiGAfc4v6EbTK0Px45
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;
}