C#: Как я могу кодировать GUID в 11 символов? - PullRequest
0 голосов
/ 31 марта 2020

Мне нравится https://www.youtube.com/watch?v= {id}

{id}: 11 символов

Я пытаюсь использовать Convert.ToBase64String

string encoded = Convert.ToBase64String(guid.ToByteArray())
                .Replace("/", "_")
                .Replace("+", "-").Replace("=", "");

вот так

Размер GUID сокращается только до 22 символов.

Как можно кодировать GUID до 11 идентификаторов символов (или менее 22 символов)

1 Ответ

1 голос
/ 31 марта 2020

Это неправильный ответ c, но он может дать вам идентификатор только с 11 символами.

В C# значение long имеет 64 бита, которые, если закодированы с Base64, будут 12 символов, включая 1 отступ =. Если мы обрежем отступ =, будет 11 символов.

Одна из сумасшедших идей здесь заключается в том, что мы можем использовать комбинацию Unix Epoch и счетчик для одного значения эпохи, чтобы сформировать значение long , Unix Epoch в C# DateTimeOffset.ToUnixEpochMilliseconds имеет формат long, но первые 2 байта из 8 байтов всегда равны 0, поскольку в противном случае значение времени даты будет больше, чем максимальное значение времени даты. Таким образом, это дает нам 2 байта для размещения счетчика ushort.

Таким образом, всего, пока число генерации идентификатора не превышает 65536 в миллисекунду, мы можем иметь уникальный идентификатор:

// 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 '='
var shortUid = Convert.ToBase64String(epochBytes).TrimEnd('=');
...