我制作了一个简单的应用程序来加密和解密档案。但是当我加载一个像 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 字节十六进制值
0 评论