我熟悉csv
Python模块,并认为在我的情况下这是必要的,因为我有一些字段包含分隔符(|
而不是,
,但那是不相关的)在引号内。
但是,我也在寻找每个原始行的字节数长度 previous 来分割成列。我不能指望数据总是引用一列,我不知道/ csv
是否会剥离外部引号,所以我不认为(但可能是错误的)只是加入我的分隔符将重现原始行字符串(减少CRLF字符)。意思是,我不肯定以下的工作:
with open(fname) as fh:
reader = csv.reader(fh, delimiter="|")
for row in reader:
original = "|".join(row) ## maybe?
我已经尝试查看csv
以查看是否有任何内容我可以使用/ monkey-patch用于此目的,但由于_csv.reader
是.so
,我不知道怎么搞乱。
如果我正在处理XY问题,我的最终目标是通读CSV文件,提取某些字段及其整体文件偏移量,以创建一种查找索引。这样,稍后,当我有一个候选值列表时,我可以检查每个文件的偏移量和seek()
,而不是再次查看整个文件。作为一个规模的想法,我可能有100k值来查找10GB文件,所以重新读取文件100k倍对我来说效率不高。我对除CSV模块之外的其他建议持开放态度,但仍需要csv
- 就像智能解析行为一样。
编辑:不确定如何使标题和正文已经解释清楚 - 仅仅seek()
- 文件句柄是不够的,因为我还需要解析这些行为csv
以便提取其他信息。
答案 0 :(得分:5)
您不能将_csv.reader
作为子类,但csvfile
constructor的 csv.reader()
参数只需“类似文件”宾语”。这意味着您可以提供自己的类的实例来执行一些预处理 - 例如记住最后一行读取的长度和文件偏移量。这是一个显示确切的实现。请注意,行长不包括行尾字符。它还显示了在读取文件后如何存储和使用每行/行的偏移量。
import csv
class CSVInputFile(object):
""" File-like object. """
def __init__(self, file):
self.file = file
self.offset = None
self.linelen = None
def __iter__(self):
return self
def __next__(self):
offset = self.file.tell()
data = self.file.readline()
if not data:
raise StopIteration
self.offset = offset
self.linelen = len(data)
return data
next = __next__
offsets = [] # remember where each row starts
fname = 'unparsed.csv'
with open(fname) as fh:
csvfile = CSVInputFile(fh)
for row in csv.reader(csvfile, delimiter="|"):
print('offset: {}, linelen: {}, row: {}'.format(
csvfile.offset, csvfile.linelen, row)) # file offset and length of row
offsets.append(csvfile.offset) # remember where each row started
答案 1 :(得分:2)
根据性能要求和数据大小,低技术解决方案是简单地读取文件两次。首先获取每行的长度,然后通过csv解析器运行数据。在我有点过时的Mac上,我可以在一秒钟内读取和计算2-3百万行的长度,这不是一个巨大的性能影响。