哈希及文件操做

1.哈希 hashpython

在將文件操做的方法以前,咱們先來對上節的知識作一個拓展,就是哈希算法,那麼什麼是哈希算法呢?算法

(1)哈希:hash,通常翻譯作散列、雜湊,或音譯爲哈希,是把任意長度的輸入(又叫作預映射pre-image)經過散列算法變換成固定長度的輸出,該輸出就是散列值。數據庫

這種轉換是一種壓縮映射,也就是,散列值的空間一般遠小於輸入的空間。函數

哈希算法的輸入能夠是字符串,能夠是數據,能夠是任何文件,通過哈希運算後,都變成一個固定長度的輸出,該輸出就是哈希值。區塊鏈

>>> hash('我愛你')
3471388576844338423
>>> hash('小猿圈')
5000768010434506639

如上所示,輸入「我愛你」三個字,通過哈希運算後,會獲得一個隨機數列,並且無論你的輸入文件多大,最後獲得的結果都是這麼一個固定長度的數列,即便你輸入的是一部電影,輸出也是這麼大。編碼

 

(2)特性:加密

  1.不可逆性:在具有編碼功能的同時,哈希算法也做爲一種加密算法存在。即,你沒法經過分析哈希值計算出源文件的樣子。spa

  不管是什麼形式,任意大小的輸入,最終結果都是一串長度相等的隨機數列,所以你沒法經過哈希值來推斷數據本來的樣子。翻譯

  2.計算極快:不管是一個5G的電影仍是一個5k的文件,運用哈希算法計算量都極小,很快就能夠計算出哈希值。code

 

(3)用途:

哈希算法的不可逆特性使其在如下領域使用普遍

  1. 密碼,咱們平常使用的各類電子密碼本質上都是基於hash的,你不用擔憂支付寶的工做人員會把你的密碼泄漏給第三方,由於你的登陸密碼是先通過 hash+各類複雜算法得出密文後 再存進支付寶的數據庫裏的

  2. 文件完整性校驗,經過對文件進行hash,得出一段hash值 ,這樣文件內容之後被修改了,hash值就會變。 MD5 Hash算法的」數字指紋」特性,使它成爲應用最普遍的一種文件完整性校驗和(Checksum)算法,很多Unix系統有提供計算md5 checksum的命令。

  3. 數字簽名,數字簽名技術是將摘要信息用發送者的私鑰加密,與原文一塊兒傳送給接收者。接收者只有用發送者的公鑰才能解密被加密的摘要信息,而後用HASH函數對收到的原文產生一個摘要信息,與解密的摘要信息對比。若是相同,則說明收到的信息是完整的,在傳輸過程當中沒有被修改,不然說明信息被修改過,所以數字簽名可以驗證信息的完整性。

此外,hash算法在區塊鏈領域也使用普遍。

 

(4)在Python中基於HASH的數據類型是dict (字典)和set (集合)。以前說到的字典查詢速度極快,以及集合天生去重就是運用了hash的特性。如下能夠做一下了解。

1.dict查詢速度快

假設一個dict中有不少信息,dict會將每個key進行哈希,將全部的哈希值按照從大到小的順序放到一個列表中,如keys=[ -22,-10,11,23,99]

當須要查找某個信息時,dict將被查找信息的key進行哈希,同一個輸入值進行哈希獲得的哈希值時相等的,所以只需再列表中找到這個哈希值,就能找到對應的value。

那麼問題來了,若是字典的數據比較小,計算機就能很快找到對應的值,可是若是字典中有幾十億條數據,怎麼快速的找到對應的值呢?

dict採用的是二分法查找,即將被查找信息的key的哈希值與列表的中間的值比較大小,這樣就能夠捨棄一半的值,這樣搜索區間就小了不少,多進行幾回這樣的操做,很快就能夠找到對應的值。

這就是字典爲什麼查詢速度快的基本原理,固然真實的算法會複雜的多。

 

2.set 天生去重

由於每存一個值到set裏時, 都要先通過hash,而後經過得出的這個hash值算出應該存在set裏的哪一個位置,存的時候會先檢查那個位置上有沒有值 ,

有的話就對比是否相等,若是相等,則再也不存儲此值。 若是不相等(即爲空),則把新值存在這。

 

2.文件操做

Python的文件操做基本經過如下步驟

f = open(filename)  # 打開文件

f.write("hello world")  # 寫操做

f.read( )  # 讀操做

f.close( )  # 保存並關閉文件

經常使用操做模式

python文件有三種基本的操做模式

r 只讀模式

w 建立模式,不能讀,用此模式操做,新的內容會覆蓋舊的內容。即清空原來的內容,寫入新的內容。

a 追加模式 ,寫入的內容會追加到文件最後

只讀模式

 

f = open('filename.text', 'r') f.readline() # 讀一行內容
content = f.read()  # 讀全部剩下的內容
print(content) f.close()

 

建立模式

f = open('filename.text', 'w') f.write('hello world')  # 此時該文件的內容爲hello world(無論原文件內容是什麼)
f.close()

追加模式

 

f = open('filename.text', 'a') f.write("小猿圈")  # 此時文件內容爲 hello world小猿圈
f.close()

循環文件

f = open('filename.tesxt' , 'r') for line in f:  # 遍歷文件的每一行
    print(line)

 

文件的其餘操做功能

 

f = open('filename.text', 'r') f.mode # 返回文件的打開方式
 f.name # 返回文件名
 f.fileno() # 返回文件句柄在內核中的索引值,之後作IO多路複用時能夠用到
 f.flush() #將內容寫入硬盤時,因爲硬盤的處理速度慢,內容會先在內存中,達到必定數量一# 起寫入硬盤提高效率,flush()方法可將內存中的數據寫入硬盤
 f.readable() # 判斷文件是否可讀
 f.readline() # 只讀一行,遇到\r 或 \n爲止
 f.seek() # 把操做文件的光標移動到指定位置 seek的長度是按字節算的 不一樣的編碼方式每 #個字符所佔的字節不一樣。如gbk編碼下中文字符佔兩個字節,utf-8編碼下中文字符佔三個字 #節,若是讀取文件時的編碼方式不一樣會致使錯誤產生。
 f.seekable() # 判斷文件是否能進行 seek 操做
 f.tell() # 返回當前文件操做光標的位置
 f.truncate() # 按指定長度截取文件  # 指定長度的話,就從文件開頭開始截斷指定長度; # 不指定長度的話,就從光標當前位置到文件 # 尾部的內容全去掉。
 f.writeable() # 判斷文件是否可寫

 

 

混合模式

文件打開還有三種混合模式,既能夠讀也能夠寫。

w+ 寫讀 ,它會建立一個新文件 ,寫一段內容,能夠再把寫的內容讀出來,通常不用。

r+ 讀寫,能讀能寫,但都是寫在文件最後,跟追加同樣,用的較多。

a+ 追加讀,文件一打開時光標會在文件尾部,寫的數據全會是追加的形式。

 

w+模式

 

f=open('filename.text','w+')  # w+讀取時 光標在最後一行 讀取時須要指定光標
 f.write("alex 23 male") f.seek(0) # 將光標移至開頭 再讀取
 print(f.readline()) f.close()

 

 

 

r+模式

f = open('filename', 'r+') f.write() # 默認往文件尾部寫
f.readline()  # 讀的是第一行

 

r+模式會將內容自動往文件末尾寫,可是若是想修改數據應該怎麼辦?

將光標移動到中間的某一個位置,插入一個信息,會發現原來的信息會被寫入的信息所覆蓋。緣由是,當你將文件存到硬盤上時,就在硬盤上劃分了一段空間,空間就那麼大,當你想寫入新的內容時,就只能覆蓋掉原來的數據,而不能使數據總體向後移。

若是想要修改文件,就只能將文件加載到內存當中,數據在內存當中能夠隨便增刪改查,以後再將修改完的數據存入硬盤覆蓋掉原來的數據,就完成了文件的修改。

 注:r+使用時,該文件必須存在。

 

當你想修改一份特別大的文件的時候,一下把文件加載到內存,是一種不明智的方式。若是想不佔內存,能夠採用一邊讀一邊寫的方式,就是建立一個新的文件,一邊從原文件中讀,一邊寫入新的文件。

f_name = "filename.txt" f_new_name = "%s.new" % f_name old_str = "eric" new_str = "alex" f = open(f_name,'r')  # 打開原文件
f_new = open(f_new_name,'w')  # 建立一個新文件
for line in f:  # 讀原文件
    if old_str in line: new_line = line.replace(old_str,new_str)  # 修改文件
    else: new_line = line f_new.write(new_line) 寫入新文件 f.close() f_new.close()

 

 

 

注:以上內容部分參考自路飛學城。

相關文章
相關標籤/搜索