.NET Short Unique Identifier

前端 未结 23 1100
忘掉有多难
忘掉有多难 2020-12-07 11:27

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

相关标签:
23条回答
  • 2020-12-07 11:56

    Based on some others, here is my solution which provides a different encoded guid which is URL (and Docker) safe and does not loose any information:

    Convert.ToBase64String(Guid.NewGuid().ToByteArray()).Replace("=", "").Replace("+", "-").Replace("/", "_");
    

    Example outputs are:

    BcfttHA780qMdHSxSBoZFA
    _4p5srPgOE2f25T_UnoGLw
    H9xR_zdfm0y-zYjdR3NOig
    
    0 讨论(0)
  • 2020-12-07 11:57

    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

    0 讨论(0)
  • 2020-12-07 11:58

    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!.

    0 讨论(0)
  • 2020-12-07 11:58

    to not lose characters (+ / -) and if you want to use your guid in an url, it must be transformed into base32

    for 10 000 000 no duplicate key

        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;
        }
    
    0 讨论(0)
  • 2020-12-07 12:00
    Guid.NewGuid().ToString().Split('-').First()
    
    0 讨论(0)
  • 2020-12-07 12:05

    Here's my small method to generate a random and short unique id. Uses a cryptographic rng for secure random number generation. Add whatever characters you need to the chars string.

    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);
    }
    
    0 讨论(0)
提交回复
热议问题