2012-11-28 52 views
2

可能重复:
How to make unique short URL with Python?别名长的字符串

我正在寻找一种方式基本上缩短到一个固定长度的字符串到磁盘上的文件的路径,从而使我可以通过它的绝对路径或通过这个别名来访问它。

我一直在寻找到使用UUID作为与有一个别名的所有路径的字典键,但我发现他们太长时间,并希望它是5-10个字符之间。我也一直在寻找一个哈希值,并想到将实际路径散列成一些我可以直接用作别名的有用字符串,然后将值存储在磁盘上的表中。我在散列的面积很新鲜,但据我所知,关键然后可以从简单的换汤不换药的路径,然后输入密钥到表会给我的价值,而不需要将其完全加载到内存中获取或从磁盘完全读取。

的最终目标是,在我的自定义浏览器,可以点使用相同的文件:

"/root/folder1/folder2/folder3/file.png" and e.g. "MTEzNDUy" 

可能会字典看起来像这样,注意固定长度的密钥。

{"MSFjak5m": "/root/folder1/folder2/file.png", 
"sofkAkfg": "/root/file.exe", 
"ASg5OFA3": "/root/file2.so", 
"fFAgeEGH": "/root/file5.so"} 

有磁盘上的查找表是可以接受的,但什么是更好的是,如果我能的路径简单地压缩到这样一个别名。最好的解决办法是为表,以便能够直接使用哈希查找一个值,而不是不必存储键/值对,因为它似乎那将意味着我会做一个散列获得别名,然后字典与执行另一个散列基于该键找到值..请纠正我,如果我错了。

条目的数目将是大约100 000和所有的操作将优选的Python下被保持。

由于

编辑
执行的几个测试用编码MD5哈希以及使用该结果作为密钥的一部分。我发现使用前4个字符给我的冲突率约为每600个条目1。使用第一个5给我的碰撞率为1/40 000.

这些条目将在正常运行时以每天约5次的速率创建一个,并且在高峰时间以最高速率每天100个,千万不要超过最多100万条目。

考虑到这一点,我最有可能通过将它与已存储的内容进行比较来检查散列的唯一性,并且只需通过任一方式处理即可。答:警告用户无法创建路径并且他必须选择另一个名称,或者B:增加散列中允许的字符数,直到找到唯一的散列。在这一点上,这两者似乎都可以接受。

(旁注中,检查对存储的哈希表击败使用散列函数的目的的散列?)对于Windows上的测试

代码。仅对文件夹进行测试,我的驱动器上大约有5万个。

import hashlib 
from random import shuffle 

def shuffle_string(word): 
    word = list(word) 
    shuffle(word) 
    return ''.join(word) 

tests = 10 
chars = 5 
_entries = 0 
_hashes = {} 
for test in xrange(tests): 
    for path, _d, _f in os.walk('c:/'): 

     unique_path = "%s%i" % (path, test) 
     key = hashlib.md5(unique_path).digest().encode('base64').strip()[:chars] 
     _hashes[key] = unique_path 
     _entries += 1 

total_collisions = _entries-len(_hashes) 

print "%s Entries \nTests: %s\nChars: %s" % (_entries, tests, chars) 
if total_collisions: 
    average_collisions = total_collisions/float(tests) 
    odds = _entries/float(average_collisions) 
    print "%s collisions per %s entries" % (average_collisions, _entries) 
    print "odds: 1 in %s" % odds 

    if odds: 
     print "chance: %s%%" % (1/(_entries/float(average_collisions))) 
else: 
    print "No collisions occured" 
+2

你知道鸽子的原理吗? – delnan

+0

我不是,但我明白你的意思。说得好! –

回答

1

考虑使用hashlib标准模块来计算字符串的哈希和一对{hash: string}存储到您的dict

+0

原谅我没有完全理解,但我已经尝试了hashlib内部的可用算法,并且它们中的任何一个都没有达到我要查找的长度,MD5十六进制大约在32个字符处,base64编码大约相当于24个时候散列:“C:\ dropbox \ storage \ projects \ beast \ jobs \ default \ database \ asset \ characters” –

+0

它将始终具有相同的长度,由哈希算法的参数指定。您使用的算法可能会有输出散列长度的选项。 –

+0

另外,你可以试着用'hash&0xFFFFFFFF'来得到一个4字节的十六进制散列,尽管我不确定在截断后它是否仍然是无冲突的(可能不是)。 –