哈希及文件操作


1.哈希 hash

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

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

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

哈希算法的輸入可以是字符串,可以是數據,可以是任何文件,經過哈希運算后,都變成一個固定長度的輸出,該輸出就是哈希值。

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

如上所示,輸入“我愛你”三個字,經過哈希運算后,會得到一個隨機數列,而且不管你的輸入文件多大,最后得到的結果都是這么一個固定長度的數列,即使你輸入的是一部電影,輸出也是這么大。

 

(2)特性:

  1.不可逆性:在具備編碼功能的同時,哈希算法也作為一種加密算法存在。即,你無法通過分析哈希值計算出源文件的樣子。

  無論是什么形式,任意大小的輸入,最終結果都是一串長度相等的隨機數列,因此你無法通過哈希值來推斷數據原本的樣子。

  2.計算極快:不論是一個5G的電影還是一個5k的文件,運用哈希算法計算量都極小,很快就可以計算出哈希值。

 

(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()

 

 

 

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM