我需要.NET中的唯一标识符(不能使用GUID,因为这种情况太长了。)
人们是否认为使用here的算法是一个很好的候选人,或者您有其他建议吗?
答案 0 :(得分:67)
也在这里 YouTube-like GUID
您可以使用Base64:
string base64Guid = Convert.ToBase64String(Guid.NewGuid().ToByteArray());
生成一个像E1HKfn68Pkms5zsZsvKONw ==这样的字符串。因为GUID是 总是128位,你可以省略你知道永远的== 出现在最后,这将给你一个22个字符的字符串。这个 并不像YouTube那么短。
答案 1 :(得分:26)
我使用与Dor Cohen类似的方法,但删除了一些特殊字符:
var uid = Regex.Replace(Convert.ToBase64String(Guid.NewGuid().ToByteArray()), "[/+=]", "");
这将只输出字母数字字符。 UID不保证总是具有相同的长度。这是一个示例运行:
vmKo0zws8k28fR4V4Hgmw
TKbhS0G2V0KqtpHOU8e6Ug
rfDi1RdO0aQHTosh9dVvw
3jhCD75fUWjQek8XRmMg
CQUg1lXIXkWG8KDFy7z6Ow
bvyxW5aj10OmKA5KMhppw
pIMK8eq5kyvLK67xtsIDg
VX4oljGWpkSQGR2OvGoOQ
NOHBjUUHv06yIc7EvotRg
iMniAuUG9kiGLwBtBQByfg
答案 2 :(得分:11)
简单易用的包装。我将它用于临时请求id生成器。
https://www.nuget.org/packages/shortid
https://github.com/bolorundurowb/shortid
使用System.Random
string id = ShortId.Generate();
// id = KXTR_VzGVUoOY
(来自github页面)
如果要通过指定是否需要数字,特殊字符和长度来控制生成的id类型,请调用Generate方法并传递三个参数,第一个是布尔表示是否需要数字,第二个是布尔表示是否需要特殊字符,最后一个数字表示您的长度偏好。
string id = ShortId.Generate(true, false, 12);
// id = VvoCDPazES_w
答案 3 :(得分:10)
var ticks = new DateTime(2016,1,1).Ticks;
var ans = DateTime.Now.Ticks - ticks;
var uniqueId = ans.ToString("x");
保持基准日期(在本例中为2016年1月1日),从您开始生成这些ID开始。这将使你的id更小。
生成的数字: 3af3c14996e54
答案 4 :(得分:8)
据我所知,just stripping off a part of a GUID isn't guaranteed to be unique - 事实上,它并非独一无二。
this blog post by Jeff Atwood中提到了我所知道的保证全球唯一性的最短内容。在链接的帖子中,他讨论了缩短GUID的多种方法,最后通过Ascii85 encoding将其缩减到20个字节。
但是,如果您绝对需要一个不超过15个字节的解决方案,我恐怕您别无选择,只能使用不保证全球唯一的解决方案。
答案 5 :(得分:6)
对于我的本地应用,我正在使用这种基于时间的方法:
/// <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;
}
答案 6 :(得分:4)
IDENTITY值在数据库中应该是唯一的,但是您应该知道这些限制...例如,它使批量数据插入基本上不可能,如果您处理大量记录,这将减慢您的速度
您也可以使用日期/时间值。我见过几个数据库,他们使用日期/时间作为PK,虽然它不是超级干净 - 但它有效。如果您控制插入,则可以有效地保证值在代码中是唯一的。
答案 7 :(得分:3)
如果你的应用程序没有几个MILLIION用户,使用它在SAME MILLISECOND生成短的唯一字符串,你可以考虑使用以下功能。
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());
}
如果您只需要在未来99年内使用您的应用程序,请将yyyy更改为yy。
答案 8 :(得分:2)
这里是我的解决方案,并发安全性不高,每秒不超过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;
}
代码未优化,只是示例!。
答案 9 :(得分:1)
我知道距离发布日期还很远......:)
我有一个只生成 9个Hexa字符的生成器,例如: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");
}
}
答案 10 :(得分:1)
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)
}
用法
Guid.NewGuid().ToTinyUuid()
要转换回来不是火箭科学,所以我会留给你那么多。
答案 11 :(得分:1)
我使用以下命令创建一个唯一的GUID(35个字符)。
// Example: 7b08e3d-186b-46f0-99c8-e8252033715d
var strUniqueGuid = Guid.NewGuid().ToString();
如果您喜欢16个字符的独特GUID,请使用以下代码
// Example: 7b08e3d-186b-46f
var strUniqueGuid = Guid.NewGuid().ToString();
strUniqueGuid=strUniqueGuid.Substring(0, 16);
答案 12 :(得分:1)
在C#中,long
值具有64位,如果使用Base64编码,则将有12个字符,包括1个填充=
。如果我们修剪填充=
,将有11个字符。
一个疯狂的想法是,我们可以结合使用Unix时代和一个时代值的计数器来形成long
值。 C#DateTimeOffset.ToUnixEpochMilliseconds
中的Unix Epoch采用long
格式,但是8个字节中的前2个字节始终为0,因为否则日期时间值将大于最大日期时间值。这样就给了我们2个字节来放置一个ushort
计数器。
因此,总的来说,只要ID生成的数量不超过每毫秒65536,我们就可以拥有唯一的ID:
// This is the counter for current epoch. Counter should reset in next millisecond
ushort currentCounter = 123;
var epoch = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
// Because epoch is 64bit long, so we should have 8 bytes
var epochBytes = BitConverter.GetBytes(epoch);
if (BitConverter.IsLittleEndian)
{
// Use big endian
epochBytes = epochBytes.Reverse().ToArray();
}
// The first two bytes are always 0, because if not, the DateTime.UtcNow is greater
// than DateTime.Max, which is not possible
var counterBytes = BitConverter.GetBytes(currentCounter);
if (BitConverter.IsLittleEndian)
{
// Use big endian
counterBytes = counterBytes.Reverse().ToArray();
}
// Copy counter bytes to the first 2 bytes of the epoch bytes
Array.Copy(counterBytes, 0, epochBytes, 0, 2);
// Encode the byte array and trim padding '='
// e.g. AAsBcTCCVlg
var shortUid = Convert.ToBase64String(epochBytes).TrimEnd('=');
答案 13 :(得分:1)
基于其他一些解决方案,这是我的解决方案,它提供了不同的编码guid,该guid是URL(和Docker)安全的,并且不会丢失任何信息:
Convert.ToBase64String(Guid.NewGuid().ToByteArray()).Replace("=", "").Replace("+", "-").Replace("/", "_");
示例输出为:
BcfttHA780qMdHSxSBoZFA
_4p5srPgOE2f25T_UnoGLw
H9xR_zdfm0y-zYjdR3NOig
答案 14 :(得分:0)
以防万一只是删除连字符对任何人都有用:
Guid.NewGuid().ToString("n")
这将生成完全独特的32个字符的字符串:
5db4cee3bfd8436395d37fca2d48d5b3
82fac271c76148a3a0667c00a5da990d
答案 15 :(得分:0)
答案 16 :(得分:0)
为了不丢失字符(+ /-),并且如果要在URL中使用GUID,必须将其转换为base32
10000000,没有重复的密钥
public static List<string> guids = new List<string>();
static void Main(string[] args)
{
for (int i = 0; i < 10000000; i++)
{
var guid = Guid.NewGuid();
string encoded = BytesToBase32(guid.ToByteArray());
guids.Add(encoded);
Console.Write(".");
}
var result = guids.GroupBy(x => x)
.Where(group => group.Count() > 1)
.Select(group => group.Key);
foreach (var res in result)
Console.WriteLine($"Duplicate {res}");
Console.WriteLine($"*********** end **************");
Console.ReadLine();
}
public static string BytesToBase32(byte[] bytes)
{
const string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
string output = "";
for (int bitIndex = 0; bitIndex < bytes.Length * 8; bitIndex += 5)
{
int dualbyte = bytes[bitIndex / 8] << 8;
if (bitIndex / 8 + 1 < bytes.Length)
dualbyte |= bytes[bitIndex / 8 + 1];
dualbyte = 0x1f & (dualbyte >> (16 - bitIndex % 8 - 5));
output += alphabet[dualbyte];
}
return output;
}
答案 17 :(得分:0)
这是我生成随机且简短的唯一ID的小方法。使用加密rng进行安全的随机数生成。将所需的任何字符添加到chars
字符串中。
private string GenerateRandomId(int length)
{
char[] stringChars = new char[length];
byte[] randomBytes = new byte[length];
using (RandomNumberGenerator rng = RandomNumberGenerator.Create())
{
rng.GetBytes(randomBytes);
}
string chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (int i = 0; i < stringChars.Length; i++)
{
stringChars[i] = chars[randomBytes[i] % chars.Length];
}
return new string(stringChars);
}
答案 18 :(得分:0)
如果您不需要键入字符串,则可以使用以下内容:
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());
}
这会将Guid转换为8个字符的字符串,如下所示:
{b77a49a5-182b-42fa-83a9-824ebd6ab58d}->“䦥띺ᠫ䋺ꦃ乱檽趵”
{c5f8f7f5-8a7c-4511-b667-8ad36b446617}->“엸诙䔑架펊䑫ᝦ”
答案 19 :(得分:0)
根据@ dorcohen的回答和@ pootzko的评论。 你可以用它。电线安全。
var errorId = System.Web.HttpServerUtility.UrlTokenEncode(Guid.NewGuid().ToByteArray());
答案 20 :(得分:-1)
22个字符,网址安全,并保留Guid的唯一性。
// 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);
输出:
yDXWhiGAfc4v6EbTK0Px45
答案 21 :(得分:-1)
你可以使用
preg_match('#^(.*?\n\n){0,100}#',$string,$match)
仅code = await UserManager.GenerateChangePhoneNumberTokenAsync(input.UserId, input.MobileNumber);
个不错的字符,6
,599527
当用户对其进行验证时
143354
希望这能帮到你
答案 22 :(得分:-2)
private static readonly object _getUniqueIdLock = new object();
public static string GetUniqueId()
{
lock(_getUniqueIdLock)
{
System.Threading.Thread.Sleep(1);
return DateTime.UtcNow.Ticks.ToString("X");
}
}
答案 23 :(得分:-3)
我使用Guid.NewGuid().ToString().Split('-')[0]
,它获取数组中由“ - ”分隔的第一项。它足以代表一个独特的密钥。
答案 24 :(得分:-4)
Guid.NewGuid().ToString().Split('-').First()