3

我在 python 中编写了一个小型加密模块,其任务是加密文件并将结果放入 tarfile。要加密的原始文件可以很大,但这不是问题,因为我的程序一次只需要处理一小块数据,可以即时加密并存储。

我正在寻找一种方法来避免分两次执行,首先将所有数据写入临时文件,然后将结果插入 tarfile。

基本上我执行以下操作(其中 generator_encryptor 是一个简单的生成器,它产生从源文件读取的数据块)。:

t = tarfile.open("target.tar", "w")
tmp = file('content', 'wb')
for chunk in generator_encryptor("sourcefile"):
   tmp.write(chunks)
tmp.close()
t.add(content)
t.close()

我有点恼火必须使用临时文件作为我的文件它应该很容易直接在 tar 文件中写入块,但是将每个块收集在单个字符串中并使用类似 t.addfile('content', StringIO( bigcipheredstring) 似乎被排除在外,因为我不能保证我有足够的内存来存储旧的 bigcipheredstring。

任何提示如何做到这一点?

4

4 回答 4

4

您可以创建自己的类似文件的对象并传递给 TarFile.addfile。您的类文件对象将在 fileobj.read() 方法中动态生成加密内容。

于 2009-09-07T14:41:10.740 回答
2

嗯?你不能只使用subprocess模块来运行管道到 tar 吗?这样,就不需要临时文件。当然,如果您无法生成足够小的数据块以适合 RAM,这将不起作用,但如果您有这个问题,那么 tar 不是问题。

于 2009-09-07T14:41:20.770 回答
2

基本上使用类似文件的对象并将其传递给 TarFile.addfile 就可以了,但是仍然存在一些问题。

  • 我需要在一开始就知道完整的加密文件大小
  • tarfile 访问 read 方法的方式是,自定义类文件对象必须始终返回完整的读取缓冲区,或者 tarfile 假设它是文件结尾。它会导致 read 方法的代码中的一些非常低效的缓冲区复制,但要么就是这样,要么更改 tarfile 模块。

生成的代码如下,基本上我必须编写一个包装类,将我现有的生成器转换为类似文件的对象。我还在我的示例中添加了 GeneratorEncrypto 类以使代码更完整。您会注意到它有一个 len 方法,该方法返回写入文件的长度(但要理解它只是一个没有任何用处的虚拟占位符)。

import tarfile

class GeneratorEncryptor(object):
    """Dummy class for testing purpose

       The real one perform on the fly encryption of source file
    """
    def __init__(self, source):
        self.source = source
        self.BLOCKSIZE = 1024
        self.NBBLOCKS = 1000

    def __call__(self):
        for c in range(0, self.NBBLOCKS):
            yield self.BLOCKSIZE * str(c%10)

    def __len__(self):
        return self.BLOCKSIZE * self.NBBLOCKS

class GeneratorToFile(object):
    """Transform a data generator into a conventional file handle
    """
    def __init__(self, generator):
        self.buf = ''
        self.generator = generator()

    def read(self, size):
        chunk = self.buf
        while len(chunk) < size:
            try:
                chunk = chunk + self.generator.next()
            except StopIteration:
                self.buf = ''
                return chunk
        self.buf = chunk[size:]
        return chunk[:size]

t = tarfile.open("target.tar", "w")
tmp = file('content', 'wb')
generator = GeneratorEncryptor("source")
ti = t.gettarinfo(name = "content")
ti.size = len(generator)
t.addfile(ti, fileobj = GeneratorToFile(generator))
t.close()
于 2009-09-20T23:53:26.860 回答
1

我想您需要了解 tar 格式的工作原理,并自己处理 tar 编写。也许这会有所帮助?

http://mail.python.org/pipermail/python-list/2001-August/100796.html

于 2009-09-07T14:39:04.860 回答