拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 读取大档案使用100%存储器,我的整个计算机都死机了

读取大档案使用100%存储器,我的整个计算机都死机了

白鹭 - 2022-02-22 2112 0 0

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

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *