我想为数据库记录使用UUID,但是如果我使用它作为URL,我希望它是5到8个字符。
我知道我需要使用SecureRandom和base64,但是我如何指定我需要的长度?
发布于 2014-10-29 03:58:00
正如另一个答案指出的那样,你不能将真正的UUID缩短到5-8个字符,但你可以将它们缩短一些。UUID是128位整数,等于32位十六进制数字。您可以轻松地存储每个字符6位,并将长度缩短到22个字符,这就是base64编码。标准的base64编码使用大小写字母、数字以及"+“和"/”来完成它。如果您将"+“和"/”替换为"-“和"_”,您将得到一个不需要进行url编码的字符串。您可以这样做(使用UUIDTools创建UUID):
uuid = UUIDTools::UUID.random_create
str = [uuid.raw].pack('m*').tr('+/','-_').slice(0..21)要让你的价值回归:
(str + "==\n").tr('-_','+/').unpack('m*').first if str =~ /^[a-zA-Z0-9_\-]{22}$/假设可以将UUID转换为原始格式,其中它是一个16个8位字符的字符串。下面是一个irb会话,展示了一个真实的示例:
2.1.1 :016 > uuid=UUIDTools::UUID.random_create
=> #<UUID:0x83f1e98c UUID:20d07b6c-52af-4e53-afea-6b3ad0d0c627>
2.1.1 :017 > uuid.raw
=> " \xD0{lR\xAFNS\xAF\xEAk:\xD0\xD0\xC6'"
2.1.1 :018 > str = [uuid.raw].pack('m*').tr('+/','-_').slice(0..21)
=> "INB7bFKvTlOv6ms60NDGJw"
2.1.1 :019 > uuid2 = (str + "==\n").tr('-_','+/').unpack('m*').first
=> " \xD0{lR\xAFNS\xAF\xEAk:\xD0\xD0\xC6'"
2.1.1 :022 > UUIDTools::UUID.parse_raw(uuid2)
=> #<UUID:0x849e6b44 UUID:20d07b6c-52af-4e53-afea-6b3ad0d0c627> 我在各种网站上使用这种方法,我通常使用Postgres来生成UUID作为表的主键,并将它们作为ids进行传递。它不会节省很多空间,但它确实使一些URL可以放在80个字符的行中,而标准格式的完整UUID不能。
发布于 2018-02-17 07:22:55
我基于Michael Chaney创建了两个单行函数
def encode(uuid)
[uuid.tr('-', '').scan(/../).map(&:hex).pack('c*')].pack('m*').tr('+/', '-_').slice(0..21)
end
def decode(short_id)
(short_id.tr('-_', '+/') + '==').unpack('m0').first.unpack('H8H4H4H4H12').join('-')
end
uuid = "355bf501-ffea-4f5a-a9e2-16074de6fcf2"
=> "355bf501-ffea-4f5a-a9e2-16074de6fcf2"
encode(uuid)
=> "NVv1Af_qT1qp4hYHTeb88g"
decode(_)
=> "355bf501-ffea-4f5a-a9e2-16074de6fcf2发布于 2020-08-05 18:16:23
我使用62个(Base62)字符的字母表,因为我不想在我的缩短UUID中使用-和_。UUID缩写程序将36长的UUID缩短为22个字符的字符串。我在Rails中使用这个UUID缩写。根据需要更改字母表。
下面是我的UUID缩写:
代码
# lib/uuid_shortener.rb
module UuidShortener
ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
ALPHABET_HASH = ALPHABET.each_char.with_index.each_with_object({}) { |(k, v), h| h[k] = v; }
BASE = ALPHABET.length
class << self
def shorten(uuid)
num = uuid.tr('-', '').to_i(16)
return '0' if num.zero?
return nil if num.negative?
str = ''
while num.positive?
str = ALPHABET[num % BASE] + str
num /= BASE
end
str
end
def expand(suid)
num = i = 0
len = suid.length - 1
while i < suid.length
pow = BASE**(len - i)
num += ALPHABET_HASH[suid[i]] * pow
i += 1
end
num.to_s(16).rjust(32, '0').unpack('A8A4A4A4A12').join('-')
end
end
end用法
> uuid = SecureRandom.uuid
> uuid
=> "2ff7b050-2a37-4d52-a8f0-76cffccbefe3"> suid = UuidShortener.shorten(uuid)
> suid
=> "1svPFI0god7vT7MNxKIrfR"> UuidShortener.expand(suid)
=> "2ff7b050-2a37-4d52-a8f0-76cffccbefe3"https://stackoverflow.com/questions/26615900
复制相似问题