2012-11-28 92 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字節的十六進制散列,儘管我不確定在截斷後它是否仍然是無衝突的(可能不是)。 –