首页 文章

在读取大文本文件时动态计算md5

提问于
浏览
1

更新的问题

我知道如何使用python从文件http://docs.python.org/3.5/library/hashlib.html#hash-algorithms创建md5哈希 . 我也知道如何逐行阅读文本文件 . 但是我的文件可能会变大,从开始到结束两次读取文件是 inefficient . 我想知道是否有可能只从光盘读取一次数据,就像在流/管道中一样,智能地组合这两个任务 . 可能是这样的:

  • 初始化md5

  • 以二进制模式打开文件

  • 将一大块数据(例如buffer_size = 65536)读入缓冲区

  • 用刚读取的块更新md5

  • 为另一个流提供缓冲区以继续处理数据

  • 使用TextIOWrapper(?)再次读取数据,但这次是文本

  • 逐行阅读文本 . 消耗缓冲区时,请询问底层以获取更多数据,直到EOF . 它会读取更多的二进制数据,更新md5,提供新的缓冲区......我可以继续逐行阅读(这就像:从第3步重复到EOF)
    _OF9_在EOF上,我已经逐行处理了所有文本,并拥有md5

目标是通过在同一文件上智能地组合二进制md5计算和基于文本的处理,从盘中读取(大)文件一次而不是两次来提高效率 .

我希望这能更好地解释它 . 再次感谢你的帮助 .

克林斯曼

2 回答

  • 1

    是的,只需创建一个hashlib.md5() object并使用每个块更新它:

    md5sum = hashlib.md5()
    
    buffer_size = 2048  # 2kb, adjust as needed.
    
    with open(..., 'rb') as fileobj:
        # read a binary file in chunks
        for chunk in iter(lambda: fileobj.read(buffer_size), b''):
            # update the hash object
            md5sum.update(chunk)
    
    # produce the final hash digest in hex.
    print(md5sum.hexdigest())
    

    如果您还需要将数据作为文本读取,则必须编写自己的包装器:

    • 实现TextIOBase API(实现与读取相关的所有stub methods),并在每次请求行时从 open(..., 'rb') 调用生成的 BufferedIOReader 对象中绘制数据 . 你必须在那时进行自己的行分割和解码 .

    • 或实现BufferedIOBase API的那个(再次实现所有存根方法),并将其作为缓冲区传递给TextIOWrapper class .

  • 1

    这似乎适用于python 3.6

    #!/usr/bin/env python
    
    import io
    import hashlib
    
    class MD5Pipe(io.BytesIO):
        def __init__(self, fd):
            self.fd = fd
            self.hasher = hashlib.md5()
        def readinto(self, b):
            l = self.fd.readinto(b)
            # print("readinto: ", l, len(b))
            if l > 0:
                self.hasher.update(b[0:l])
            return l
        def hexdigest(self):
            return self.hasher.hexdigest()
    
    blocksize = 65536
    file = "c:/temp/PIL/VTS/VTS_123.csv"
    with open(file, "rb") as fd:
        with MD5Pipe(fd) as md5:
            with io.BufferedReader(md5) as br:
                with io.TextIOWrapper(br, newline='', encoding="utf-8") as reader:
                    for line in reader:
                        print("line: ", line, end="")
    
                    print("md5: ", md5.hexdigest())
    

相关问题