Короткий уникальный идентификатор .NET
Мне нужен уникальный идентификатор в .NET (не могу использовать GUID, так как он слишком длинный для этого случая).
Неужели люди думают, что алгоритм используется здесь хороший кандидат или у вас есть другие предложения?
15 ответов:
Это один хороший - http://www.singular.co.nz/blog/archive/2007/12/20/shortguid-a-shorter-and-url-friendly-guid-in-c-sharp.aspx
и здесь YouTube-как GUID
вы можете использовать Base64:
string base64Guid = Convert.ToBase64String(Guid.NewGuid().ToByteArray());
который генерирует строку типа E1HKfn68Pkms5zsZsvKONw==. Так как GUID-это всегда 128 бит, вы можете опустить == что вы знаете, всегда будет присутствует в конце, и это даст вам 22 персонажа строка. Этот это не так коротко, как YouTube, хотя.
Я использую аналогичный подход, как Дор Коэн, но удаление некоторых специальных символов:
var uid = Regex.Replace(Convert.ToBase64String(Guid.NewGuid().ToByteArray()), "[/+=]", "");
это выведет только буквенно-цифровые символы. Не гарантируется, что uid всегда имеют одинаковую длину. Вот пример выполнения:
vmKo0zws8k28fR4V4Hgmw TKbhS0G2V0KqtpHOU8e6Ug rfDi1RdO0aQHTosh9dVvw 3jhCD75fUWjQek8XRmMg CQUg1lXIXkWG8KDFy7z6Ow bvyxW5aj10OmKA5KMhppw pIMK8eq5kyvLK67xtsIDg VX4oljGWpkSQGR2OvGoOQ NOHBjUUHv06yIc7EvotRg iMniAuUG9kiGLwBtBQByfg
var ticks = new DateTime(2016,1,1).Ticks; var ans = DateTime.Now.Ticks - ticks; var uniqueId = ans.ToString("x");
сохранить базовую дату (которая в данном случае является 1 января 2016 года) от того, когда вы начнете генерировать эти идентификаторы. Это сделает ваши идентификаторы более мелкими.
насколько я знаю, просто удаление части GUID не гарантируется быть уникальным - в самом деле, это далеко не уникальный.
самая короткая вещь, которую я знаю, что гарантирует глобальную уникальность, представлена в это сообщение в блоге Джеффа Этвуда. В связанном сообщении он обсуждает несколько способов сократить GUID, и в конце концов получает его до 20 байт через кодировка Ascii85.
однако, если вам абсолютно необходимо решение это не более 15 байт, я боюсь, что у вас нет другого выбора, кроме как использовать то, что не обязательно быть глобально уникальным.
для моего локального приложения я использую этот подход на основе времени:
/// <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; }
простой полезный пакет. Я использую его для временного генератора идентификаторов запросов.
https://www.nuget.org/packages/shortid
https://github.com/bolorundurowb/shortid
использует
System.Random
string id = ShortId.Generate(); // id = KXTR_VzGVUoOY
(со страницы github)
Если вы хотите управлять типом генерируемого идентификатора, указав, нужны ли вам числа, специальные символы и длина, вызовите метод Generate и передайте три параметра, первый-логическое значение, указывающее, нужны ли вам числа, второй-логическое значение, указывающее, нужны ли вам специальные символы, последний-число, указывающее ваше предпочтение длины.
string id = ShortId.Generate(true, false, 12); // id = VvoCDPazES_w
значения идентификаторов должны быть уникальными в базе данных, но вы должны знать об ограничениях... например, это делает массовые вставки данных практически невозможными, что замедлит вас, если вы работаете с очень большим количеством записей.
вы также можете использовать значение даты/времени. Я видел несколько баз данных, где они используют дату/время, чтобы быть ПК, и хотя это не супер чистый - он работает. Если вы управляете вставками, вы можете эффективно гарантировать, что значения будет уникальным в коде.
здесь мое решение, не безопасно для параллелизма, не более 1000 GUID в секунду и потокобезопасно.
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; }
код не оптимизирован, просто образец!.
Если в вашем приложении нет нескольких миллионов человек, используя которые генерируют короткую уникальную строку в ту же миллисекунду, вы можете подумать об использовании функции ниже.
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()); }
измените yyyy на yy, если вам просто нужно использовать свое приложение в следующем 99 году.
обновление 20160511: правильная случайная функция
- Добавить объект блокировки
- перемещение случайной величины из функции RandomString
Ref
Я знаю, что это довольно далеко от даты публикации... :)
У меня есть генератор, который производит только 9 символов Гекса, например: 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"); } }
на основе ответа @dorcohen и комментария @pootzko. Вы можете использовать это. Это безопасно по проводам.
var errorId = System.Web.HttpServerUtility.UrlTokenEncode(Guid.NewGuid().ToByteArray());
Я использую следующее Для создания уникального guid (35 символов).
// Example: 7b08e3d-186b-46f0-99c8-e8252033715d var strUniqueGuid = Guid.NewGuid().ToString();
Если вам нравится уникальный идентификатор guid с 16 символами, используйте приведенный ниже код
// Example: 7b08e3d-186b-46f var strUniqueGuid = Guid.NewGuid().ToString(); strUniqueGuid=strUniqueGuid.Substring(0, 16);
можно использовать
code = await UserManager.GenerateChangePhoneNumberTokenAsync(input.UserId, input.MobileNumber);
его
6
хорошие персонажи только599527
,143354
и когда пользователь virify это просто
var result = await UserManager.VerifyChangePhoneNumberTokenAsync(input.UserId, input.Token, input.MobileNumber);
надеюсь, что это поможет вам