Sim*_*son 63 python url base64
我想要一种在URL中表示整数的最短方式.例如,11234可以使用十六进制缩短为"2be2".由于base64使用的是64字符编码,因此应该可以使用比十六进制更少的字符来表示base64中的整数.问题是我无法弄清楚使用Python将整数转换为base64(以及再返回)的最简洁方法.
base64模块有处理字节串的方法 - 所以也许一个解决方案是将一个整数转换为二进制表示形式作为Python字符串...但我不知道如何做到这一点.
Mil*_*les 60
这个答案与Douglas Leeder的精神相似,但有以下变化:
它不是首先将数字转换为字节串(基数256),而是将其直接转换为base 64,这样可以让您使用符号字符表示负数.
import string
ALPHABET = string.ascii_uppercase + string.ascii_lowercase + \
string.digits + '-_'
ALPHABET_REVERSE = dict((c, i) for (i, c) in enumerate(ALPHABET))
BASE = len(ALPHABET)
SIGN_CHARACTER = '$'
def num_encode(n):
if n < 0:
return SIGN_CHARACTER + num_encode(-n)
s = []
while True:
n, r = divmod(n, BASE)
s.append(ALPHABET[r])
if n == 0: break
return ''.join(reversed(s))
def num_decode(s):
if s[0] == SIGN_CHARACTER:
return -num_decode(s[1:])
n = 0
for c in s:
n = n * BASE + ALPHABET_REVERSE[c]
return n
Run Code Online (Sandbox Code Playgroud) >>> num_encode(0)
'A'
>>> num_encode(64)
'BA'
>>> num_encode(-(64**5-1))
'$_____'
Run Code Online (Sandbox Code Playgroud)
一些附注:
Ale*_*erg 18
关于Base64的所有答案都是非常合理的解决方案.但它们在技术上是不正确的.要将整数转换为可能的最短URL安全字符串,您需要的是base 66(有66个URL安全字符).
该代码如下所示:
from io import StringIO
import urllib
BASE66_ALPHABET = u"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_.~"
BASE = len(BASE66_ALPHABET)
def hexahexacontadecimal_encode_int(n):
if n == 0:
return BASE66_ALPHABET[0].encode('ascii')
r = StringIO()
while n:
n, t = divmod(n, BASE)
r.write(BASE66_ALPHABET[t])
return r.getvalue().encode('ascii')[::-1]
Run Code Online (Sandbox Code Playgroud)
这是一个完整的实现源代码,可以随时使用pip可安装包:
https://github.com/aljungberg/hexahexacontadecimal
Bri*_*ian 14
你可能不需要真正的base64编码 - 它会添加填充等,甚至可能导致比小数字更大的字符串.如果不需要与其他任何东西进行互操作,只需使用您自己的编码即可.例如.这是一个将编码到任何基数的函数(注意数字实际上是存储最不重要的,以避免额外的reverse()调用:
def make_encoder(baseString):
size = len(baseString)
d = dict((ch, i) for (i, ch) in enumerate(baseString)) # Map from char -> value
if len(d) != size:
raise Exception("Duplicate characters in encoding string")
def encode(x):
if x==0: return baseString[0] # Only needed if don't want '' for 0
l=[]
while x>0:
l.append(baseString[x % size])
x //= size
return ''.join(l)
def decode(s):
return sum(d[ch] * size**i for (i,ch) in enumerate(s))
return encode, decode
# Base 64 version:
encode,decode = make_encoder("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
assert decode(encode(435346456456)) == 435346456456
Run Code Online (Sandbox Code Playgroud)
这样做的好处是,只需向编码器的基本字符串添加适当的字符,即可使用所需的任何基础.
请注意,较大基数的收益不会那么大.base 64只会将大小减小到base 16的2/3rds(6位/ char而不是4位).每次加倍只会为每个字符增加一位.除非你真的需要压缩东西,否则只使用十六进制可能是最简单和最快的选择.
编码n:
data = ''
while n > 0:
data = chr(n & 255) + data
n = n >> 8
encoded = base64.urlsafe_b64encode(data).rstrip('=')
Run Code Online (Sandbox Code Playgroud)
要解码s:
data = base64.urlsafe_b64decode(s + '===')
decoded = 0
while len(data) > 0:
decoded = (decoded << 8) | ord(data[0])
data = data[1:]
Run Code Online (Sandbox Code Playgroud)
与其他一些"最佳"编码一样,您可以根据RFC 1738 使用73个字符(如果您将"+"视为可用,则实际为74个):
alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_`\"!$'()*,-."
encoded = ''
while n > 0:
n, r = divmod(n, len(alphabet))
encoded = alphabet[r] + encoded
Run Code Online (Sandbox Code Playgroud)
和解码:
decoded = 0
while len(s) > 0:
decoded = decoded * len(alphabet) + alphabet.find(s[0])
s = s[1:]
Run Code Online (Sandbox Code Playgroud)
简单的一点是将字节字符串转换为Web安全的base64:
import base64
output = base64.urlsafe_b64encode(s)
Run Code Online (Sandbox Code Playgroud)
棘手的位是第一步 - 将整数转换为字节串.
如果你的整数很小,你最好用十六进制编码它们 - 见saua
否则(hacky递归版):
def convertIntToByteString(i):
if i == 0:
return ""
else:
return convertIntToByteString(i >> 8) + chr(i & 255)
Run Code Online (Sandbox Code Playgroud)
您不需要base64编码,您希望在数字基数X中表示基数为10的数字.
如果您希望您的基数10数字以26个字母表示,您可以使用:http: //en.wikipedia.org/wiki/Hexavigesimal.(您可以通过使用所有合法的URL字符将该示例扩展为更大的基础)
你应该至少能得到38(26个字母,10个数字,+,_)