Skip to main content
 首页 » 编程设计

python之长字符串的别名

2025年05月04日23leader

<分区>

Possible Duplicate:
How to make unique short URL with Python?

我正在寻找一种方法,从本质上将磁盘上文件的路径缩短为固定长度的字符串,以便我可以通过绝对路径或此别名访问它。

我一直在研究使用 UUID 作为字典的键,该字典包含所有具有别名的路径,但我发现它们太长并且希望它在 5-10 个字符之间。我也一直在查看散列并考虑将实际路径散列为一些有用的字符串,我可以直接将其用作别名,然后将值存储在磁盘上的表中。我在散列领域非常新鲜,但据我了解,可以通过简单地重新散列路径然后将 key 输入表中来获取 key ,而无需将其完全加载到内存中或从磁盘中完全读取。

最终目标是,在我的自定义浏览器中,能够使用以下方法指向同一个文件:

"/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 哈希进行编码并将部分结果用作 key 来执行一些测试。我发现使用前 4 个字符给我的碰撞率约为每 600 个条目 1 个。使用前 5 个给了我 1/40 000 的碰撞率。

这些条目将在正常操作下一次创建一个,速率约为 5 个/天,高峰时段的最大速率为 100 个/天,永远不会超过 1000000 个条目的最大值。

考虑到这一点,我很可能会通过将它与已经存储的内容进行比较来检查我获得的哈希的唯一性,并通过以下任一方式简单地处理它,A:警告用户无法创建路径并且他必须选择另一个名字,或者 B:增加散列中允许的字符数,直到找到唯一的散列。在这一点上,其中任何一个似乎都可以接受。

(旁注,根据存储的哈希表检查哈希是否违背了使用哈希函数的目的?)

Windows 测试代码。仅针对文件夹进行测试,我的驱动器上有大约 50 000 个。

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"