【发布时间】:2010-11-30 07:36:35
【问题描述】:
是否可以像在 YouTube (N7Et6c9nL9w) 中那样生成短 GUID?
怎么做?我想在网络应用中使用它。
【问题讨论】:
标签: c# .net url-shortener
是否可以像在 YouTube (N7Et6c9nL9w) 中那样生成短 GUID?
怎么做?我想在网络应用中使用它。
【问题讨论】:
标签: c# .net url-shortener
你可以使用 Base64:
string base64Guid = Convert.ToBase64String(Guid.NewGuid().ToByteArray());
这会生成一个类似E1HKfn68Pkms5zsZsvKONw== 的字符串。由于 GUID 始终为 128 位,因此您可以省略 ==,您知道它将始终出现在末尾,这将为您提供 22 个字符的字符串。不过,它不像 YouTube 那样短。
【讨论】:
如已接受的答案中所述,如果您在 URL 中使用 GUID,可能会导致问题。这是一个更完整的答案:
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);
【讨论】:
base64Guid.Substring(0, 22) 而不是 base64Guid.Substring(0, base64Guid.Length - 2) 吗?
Guid.NewGuid().ToString("N") 呢?
9 个字符不是 GUID。鉴于此,您可以使用 int 的十六进制表示,它为您提供 8 个字符的字符串。
您可以使用您可能已经拥有的 id。您也可以对不同的简单类型使用.GetHashCode,并且您有不同的int。您还可以异或不同的字段。如果你喜欢它,你甚至可以使用随机数 - 嘿,如果你坚持积极的态度,你的可能值远高于 2.000.000.000 ;)
【讨论】:
这不是 GUID
让我进入以下内容
它使用来自EPOCH 的TotalMilliseconds 和一组有效的字符。
这不会是全局唯一的,但对于它定义的实例来说是唯一的
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 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".ToCharArray();
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);
对于 Guid ecd65132-ab5a-4587-87b8-b875e2fe0f35,它会将其分解为 ecd65132 ,ab5a , 4587,87b8,b875e2fe0f35
但我不能保证它总是独一无二的。
更新 2: 还有一个名为 ShortGuid 的项目来获得一个 url 友好的 GUID 它可以从 / 转换为常规的 Guid
它的工作原理是将Guid 编码为 Base64,如下面的代码
public static string Encode(Guid guid)
{
string encoded = Convert.ToBase64String(guid.ToByteArray());
encoded = encoded
.Replace("/", "_")
.Replace("+", "-");
return encoded.Substring(0, 22);
}
它的好处是可以再次解码以获取Guid
public static Guid Decode(string value)
{
// avoid parsing larger strings/blobs
if (value.Length != 22)
{
throw new ArgumentException("A ShortGuid must be exactly 22 characters long. Receive a character string.");
}
string base64 = value
.Replace("_", "/")
.Replace("-", "+") + "==";
byte[] blob = Convert.FromBase64String(base64);
var guid = new Guid(blob);
var sanityCheck = Encode(guid);
if (sanityCheck != value)
{
throw new FormatException(
@"Invalid strict ShortGuid encoded string. The string '{value}' is valid URL-safe Base64, " +
@"but failed a round-trip test expecting '{sanityCheck}'."
);
}
return guid;
}
所以 Guid 4039124b-6153-4721-84dc-f56f5b057ac2 将被编码为 SxI5QFNhIUeE3PVvWwV6wg 并且输出看起来像这样。
ANf-MxRHHky2TptaXBxcwA
zpjp-stmVE6ZCbOjbeyzew
jk7P-XYFokmqgGguk_530A
81t6YZtkikGfLglibYkDhQ
qiM2GmqCK0e8wQvOSn-zLA
【讨论】:
正如其他人所提到的,YouTube 的 VideoId 在技术上并不是一个 GUID,因为它本身并不是唯一的。
根据Wikipedia:
唯一键的总数为 2128 或 3.4×1038。这个数字太 大到随机生成相同数字的概率 两次可以忽略不计。
YouTube 的 VideoId 的独特性由他们的生成器算法维护。
您可以编写自己的算法,也可以使用某种随机字符串生成器并利用 SQL 中的UNIQUE CONSTRAINT 约束来强制其唯一性。
首先,在您的数据库中创建一个UNIQUE CONSTRAINT:
ALTER TABLE MyTable
ADD CONSTRAINT UniqueUrlId
UNIQUE (UrlId);
然后,例如,生成一个随机字符串(来自 philipproplesch 的answer):
string shortUrl = System.Web.Security.Membership.GeneratePassword(11, 0);
如果生成的UrlId 足够随机且足够长,您应该很少遇到SQL 遇到重复的UrlId 时引发的异常。在这种情况下,您可以轻松地在 Web 应用中处理异常。
【讨论】:
GeneratePassword 方法的唯一问题是第二个参数实际上是针对非字母和非数字字符的最小数量。当我尝试使用0 时,我得到了几个这样的符号......
从技术上讲,它不是 Guid。 Youtube 有一个简单的随机字符串生成器,您可以使用一组允许的字符和一个随机数生成器在几分钟内完成它。
【讨论】:
这可能不是最好的解决方案,但您可以这样做:
string shortUrl = System.Web.Security.Membership.GeneratePassword(11, 0);
【讨论】:
0 时,我得到了几个这样的符号......
这个 id 可能不是全局唯一的。 GUID 应该是全局唯一的,因为它们包含不应在其他地方出现的元素(生成 ID 的机器的 MAC 地址、生成 ID 的时间等)
如果您需要的是在您的应用程序中唯一的 ID,请使用数字喷泉 - 可能将该值编码为十六进制数字。每次需要 id 时,请从数字喷泉中获取。
如果您有多个服务器分配 id,您可以获取一系列数字(几十或几千,具体取决于您分配 id 的速度),这应该可以完成工作。一个 8 位十六进制数字将为您提供 40 亿个 id - 但您的第一个 id 会短得多。
【讨论】: