YouTube-подобный GUID

Можно ли создать короткий GUID как в YouTube (N7Et6c9nL9w)?

Как это можно сделать? Я хочу использовать его в веб-приложении.

9 ответов

Решение

Вы можете использовать Base64:

string base64Guid = Convert.ToBase64String(Guid.NewGuid().ToByteArray());

Это генерирует строку как E1HKfn68Pkms5zsZsvKONw==, Поскольку GUID всегда 128 бит, вы можете опустить == вы знаете, что всегда будет присутствовать в конце, и это даст вам строку из 22 символов. Это не так коротко, как на YouTube.

Как упомянуто в принятом ответе, это может создать проблемы, если вы используете GUID в URL. Вот более полный ответ:

    public string ToShortString(Guid guid)
    {
        var base64Guid = Convert.ToBase64String(guid.ToByteArray());

        // Replace URL unfriendly characters with better ones
        base64Guid = base64Guid.Replace('+', '-').Replace('/', '_');

        // Remove the trailing ==
        return base64Guid.Substring(0, base64Guid.Length - 2);
    }

    public Guid FromShortString(string str)
    {
        str = str.Replace('_', '/').Replace('-', '+');
        var byteArray = Convert.FromBase64String(str + "==");
        return new Guid(byteArray);
    }

Использование:

        var guid = Guid.NewGuid();
        var shortStr = ToShortString(guid);
        // shortStr will look something like 2LP8GcHr-EC4D__QTizUWw
        var guid2 = FromShortString(shortStr);
        Assert.AreEqual(guid, guid2);

9 символов - это не гид. Учитывая это, вы можете использовать шестнадцатеричное представление типа int, которое дает вам строку из 8 символов.

Обновление 1: Не знаю, почему вышеупомянутое получило отрицательное мнение, но для любого задающегося вопросом:

Вы можете использовать идентификатор, который у вас уже есть. Также вы можете использовать.GetHashCode для разных простых типов, и там у вас есть разные int. Вы также можете xor различных полей. И если вам это нравится, вы можете даже использовать Случайное число - эй, у вас намного больше 2.000.000.000+ возможных значений, если вы придерживаетесь положительных результатов;)

Это не GUID

Позвольте мне перейти к следующему

Он использует TotalMilliseconds от EPOCH и допустимый набор символов.

Это не будет глобально уникальным, но уникальным для экземпляра, в котором он определяет

public string YoutubeLikeId()
{
    Thread.Sleep(1);//make everything unique while looping
    long ticks = (long)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1,0,0,0,0))).TotalMilliseconds;//EPOCH
    char[] baseChars = new char[] { '0','1','2','3','4','5','6','7','8','9',
            'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
            'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x'};

    int i = 32;
    char[] buffer = new char[i];
    int targetBase= baseChars.Length;

    do
    {
        buffer[--i] = baseChars[ticks % targetBase];
        ticks = ticks / targetBase;
    }
    while (ticks > 0);

    char[] result = new char[32 - i];
    Array.Copy(buffer, i, result, 0, 32 - i);

    return new string(result);
}

Результат будет примерно таким:

XOTgBsu
XOTgBtB
XOTgBtR
XOTgBtg
XOTgBtw
XOTgBuE

Обновление: то же самое можно сделать изGuid как

var guid = Guid.NewGuid(); 
guid.ToString("N");
guid.ToString("N").Substring(0,8);
guid.ToString("N").Substring(8,4);
guid.ToString("N").Substring(12,4);
guid.ToString("N").Substring(16,4);
guid.ToString("N").Substring(20,12);

Для гида ecd65132-ab5a-4587-87b8-b875e2fe0f35 он разбивает его на куски, как ecd65132,ab5a, 4587,87b8,b875e2fe0f35

но я не могу гарантировать, что он всегда будет уникальным.

Обновление 2: существует также проект под названием ShortGuid, чтобы получить дружественный URLGUID он может быть преобразован из / в обычный Guid

Как уже упоминалось, YouTube VideoId технически это не GUID, так как он не уникален по своей сути.

Согласно Википедии:

Общее количество уникальных ключей составляет 2128 или 3,4 × 1038. Это число настолько велико, что вероятность того, что одно и то же число будет случайно сгенерировано дважды, ничтожно мала.

Уникальность YouTube VideoId поддерживается их алгоритмом генератора.

Вы можете написать свой собственный алгоритм или использовать какой-то генератор случайных строк и использовать UNIQUE CONSTRAINT ограничение в SQL для обеспечения его уникальности.

Сначала создайте UNIQUE CONSTRAINT в вашей базе данных:

ALTER TABLE MyTable
ADD CONSTRAINT UniqueUrlId
UNIQUE (UrlId);

Затем, например, сгенерируйте случайную строку (из ответа Филиппроплеша):

string shortUrl = System.Web.Security.Membership.GeneratePassword(11, 0);

Если сгенерировано UrlId является достаточно случайным и достаточно длинным, вы редко сталкиваетесь с исключением, которое выдается, когда SQL встречает дубликат UrlId, В таком случае вы можете легко обработать исключение в вашем веб-приложении.

Технически это не гид. У Youtube есть простой генератор случайных строк, который вы, вероятно, сможете за несколько минут запустить, используя массив разрешенных символов и генератор случайных чисел.

Это может быть не лучшим решением, но вы можете сделать что-то вроде этого:

string shortUrl = System.Web.Security.Membership.GeneratePassword(11, 0);

Этот идентификатор, вероятно, не является глобально уникальным. Идентификаторы GUID должны быть глобально уникальными, поскольку они включают элементы, которые не должны встречаться в других местах (MAC-адрес компьютера, генерирующего идентификатор, время создания идентификатора и т. Д.)

Если вам нужен идентификатор, уникальный в вашем приложении, используйте фонтан чисел - возможно, кодирующее значение в виде шестнадцатеричного числа. Каждый раз, когда вам нужен идентификатор, возьмите его с номера фонтана.

Если у вас есть несколько серверов, выделяющих идентификаторы, вы можете получить диапазон чисел (несколько десятков или тысяч в зависимости от того, как быстро вы выделяете идентификаторы), и это должно сработать. 8-значный шестнадцатеричный номер даст вам 4 миллиарда идентификаторов, но ваш первый идентификатор будет намного короче.

Возможно, использование NanoId избавит вас от головной боли: https://github.com/codeyu/nanoid-net

Вы можете сделать что-то вроде:

      var id = Nanoid.Generate('1234567890abcdef', 10) //=> "4f90d13a42"

И вы можете проверить вероятность столкновения здесь: https://alex7kom.github.io/nano-nanoid-cc/

Другие вопросы по тегам