我制作了一個簡單的應用程式來加密和解密檔案。但是當我加載一個像 2gb 這樣的大檔案時,我的程式使用了 100% 的記憶體。我使用多處理和多執行緒。
poolSize = min(cpu_count(), len(fileList))
process_pool = Pool(poolSize)
thread_pool = ThreadPool(len(fileList))
lock = Lock()
worker = partial(encfile, process_pool, lock)
thread_pool.map(worker, fileList)
def encfile(process_pool, lock, file):
with open(file, 'rb') as original_file:
original = original_file.read()
encrypted = process_pool.apply(encryptfn, args=(key, original,))
with open (file, 'wb') as encrypted_file:
encrypted_file.write(encrypted)
uj5u.com熱心網友回復:
這是我的總體思路:
由于記憶體是一個問題,您必須以較小的塊讀取檔案,例如 64K 塊,然后加密每個 64K 塊并將其寫出。當然,加密塊的長度不是 64K,所以問題就變成了如何解密。因此,每個加密塊都必須以固??定長度的標頭作為前綴,該標頭只不過是編碼為 4 位元組無符號整數的后續加密塊的長度(這應該綽綽有余)。解密演算法回圈首先讀取下一個 4 位元組長度,然后從中知道接下來的加密塊有多少位元組長。
順便說一句,有沒有需要傳遞給encfile一個lock,如果你不使用它,例如,計數處理的檔案。
from tempfile import mkstemp
from os import fdopen, replace
BLOCKSIZE = 64 * 1024
ENCRYPTED_HEADER_LENGTH = 4
def encfile(process_pool, lock, file):
"""
Encrypt file in place.
"""
fd, path = mkstemp() # make a temporary file
with open(file, 'rb') as original_file, \
fdopen (fd, 'wb') as encrypted_file:
while True:
original = original_file.read(BLOCKSIZE)
if not original:
break
encrypted = process_pool.apply(encryptfn, args=(key, original))
l = len(encrypted)
l_bytes = l.to_bytes(ENCRYPTED_HEADER_LENGTH, 'big')
encrypted_file.write(l_bytes)
encrypted_file.write(encrypted)
replace(path, file)
def decfile(file):
"""
Decrypt files in place.
"""
fd, path = mkstemp() # make a temporary file
with open(file, 'rb') as encrypted_file, \
fdopen (fd, 'wb') as original_file:
while True:
l_bytes = encrypted_file.read(ENCRYPTED_HEADER_LENGTH)
if not l_bytes:
break
l = int.from_bytes(l_bytes, 'big')
encrypted = encrypted_file.read(l)
decrypted = decryptfn(key, encrypted)
original_file.write(decrypted)
replace(path, file)
解釋
塊大小越大,需要的記憶體越多(您的原始程式讀取整個檔案;該程式一次只能讀取 64K)。但我假設太小的塊大小會導致對加密的呼叫過多,這是由多處理完成的,并且需要更多的 CPU 開銷——所以這是一個權衡。64K 是任意的。如果你有記憶體,增加很多。您甚至可以嘗試 1024 * 1024 (1M)。
我之前試圖解釋以下內容,但讓我詳細說明:
因此,假設當您加密 64K 塊時,該特定 64K 塊的加密大小最終為 67,986 位元組長(不同的 64K 加密塊通常具有不同的長度,除非其未加密的值碰巧相同)。如果我只寫出沒有其他資訊的資料,我需要某種方式來知道要解密檔案首先需要讀回 67,986 位元組的資料并將其傳遞給解密方法(使用正確的密鑰,當然)因為您必須解密加密內容的精確結果,不能少也不能多位元組。換句話說,您不能只是以任意塊讀回加密檔案并將這些塊傳遞給解密方法。但那會是什么呢?因此,知道每個加密塊有多大的唯一方法是在這些塊前面加上一個標頭,該標頭給出了下一個塊的長度。
l_bytes = l.to_bytes(ENCRYPTED_HEADER_LENGTH, 'big')獲取存盤在變數中的 integerlengthl并將其編碼為大小為 ENCRYPTED_HEADER_LENGTH 的位元組陣列,以“大端”順序表示位元組從高位位元組到低位位元組排列:
>>> ENCRYPTED_HEADER_LENGTH = 4
>>> l = 67986
>>> l_bytes = l.to_bytes(ENCRYPTED_HEADER_LENGTH, 'big')
>>> l_bytes
b'\x00\x01\t\x92'
>>> l_bytes = l.to_bytes(ENCRYPTED_HEADER_LENGTH, 'little')
>>> l_bytes
b'\x92\t\x01\x00'
>>>
\t是值為 的制表符,\x09因此我們將寫出 0010992,這是 67986 的 4 位元組十六進制值
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/391062.html
