0

情况:我使用 mmap 将 CVD(ClamAV 病毒数据库)文件加载到 RAM 中。CVD 文件中每一行的格式与 CSV 文件的格式相同(':' 分隔)。以下是代码片段:

def mapping():
    with open("main.cvd", 'rt') as f:
        global mapper
        mapper = mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ)
        csv.register_dialect('delimit', delimiter=':', quoting=csv.QUOTE_NONE)

def compare(hashed):
    for row in csv.reader(mapper, dialect='delimit'):
        if row[1] == hashed:
            print('Found!')

问题:运行时返回错误_csv.Error: iterator should return strings, not bytes (did you open the file in text mode?)

问题:如何将 CSV 文件作为已加载到内存的文本读取?

附加信息1:我尝试过使用StringIO,它会抛出错误TypeError: initial_value must be str or None, not mmap.mmap

附加信息 2:我需要将文件放在 RAM 中以便更快地访问文件,并且我不能牺牲使用以下函数逐行读取它的时间readline()

4

1 回答 1

1

构造函数的csvfile参数csv.reader“可以是任何支持迭代器协议并在每次next()调用其方法时返回一个字符串的对象”。

这意味着“对象”可以是生成器函数或生成器表达式。在下面的代码中,我实现了一个名为的生成器函数mmap_file_reader(),它将内存映射中的字节转换为字符串以及yield它检测到的每一行输出。

我使mmap.mmap构造函数调用有条件,因此它也可以在 Windows 上运行。access=如果您使用关键字而不是关键字,这应该不是必需的prot=- 但我无法测试它,所以如图所示。

import csv
import mmap
import sys

def mapping():
    with open("main.cvd", 'rt') as f:
        global mapper
        if sys.platform.startswith('win32'):
            mmf = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)  # windows
        else:
            mmf = mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ)  # unix
        mapper = mmap_file_reader(mmf)
        csv.register_dialect('delimit', delimiter=':', quoting=csv.QUOTE_NONE)

def mmap_file_reader(mmf):
    '''Yield successive lines of the given memory-mapped file as strings.

    Generator function which reads and converts the bytes of the given mmapped file
    to strings and yields them one line at a time.
    '''
    while True:
        line = mmf.readline()
        if not line:  # EOF?
            return
        yield str(line, encoding='utf-8')  # convert bytes of lineread into a string

def compare(hashed):
    for row in csv.reader(mapper, dialect='delimit'):
        if row[1] == hashed:
            print('Found!')
于 2017-06-08T06:37:43.060 回答