如何使tell()函数正常工作?

3

我想打开一个文件并从上次读取的位置继续读取。我的文件很大(20MB到1GB左右)。经过一些研究,我发现tell()和seek()是最有效的方法之一。我尝试了以下代码:

opened = open(filename, "rU")   
f1 = csv.reader(opened)
k = []
for line in f1:
    k.append(opened.tell())

当我这样做时,列表中的每个值都是8272 Long。这是否意味着我不能使用这个实现?我有什么遗漏吗?谢谢你的帮助!

我在Windows 7上运行Python 2.7。

更新

在整合了这里学到的所有内容并进行试错之后,我得到了以下代码。

opened = open(filename, "rU")   
k = [0]
where = 1
for switch in opened:
    where += len(switch) + 1
    f = StringIO.StringIO(switch)
    interesting = csv.reader(f, delimiter=',')
    good_values = interesting.next()
    k.append(where)

return k

这使用户能够准确地知道在文件中要前往的位置,同时仍然能够根据其格式解析它。我并不完全确定为什么需要不断添加偏移量(似乎换行符在len()函数中没有被准确计算)。

1个回答

1

看起来csv.reader正在以8272字节的块读取文件,这就是为什么你会看到从opened.tell()返回这个数字很多次 - 直到你在0-8272范围内读取了文件中的所有行。之后,您将看到8272 * 2几次,确切的数字取决于缓冲区读取的行的长度。

因此,在您的程序中,tell()并没有像您所认为的那样给出新CSV行的偏移量。它只告诉您当前读入内部操作系统缓冲区的文件区域末尾的偏移量,该缓冲区用于实现Python IO函数的系统函数。


所以我迭代了“opened”,并将字符串的长度相加。这给出了正确的值。我仍然想使用csv reader,因为那是我正在读取的文件格式。我使用推导式来实现它。这比使用正则表达式更有效吗?有没有更有效的方法来解决这个问题? - Legen Diary
不确定您是通过理解来进行什么操作。如果您有一种方法可以正确计算给定行的偏移量,那为什么在重新启动时不执行opened.seek到上次处理的CSV行后面的文件偏移量,并将其传递给csv.reader构造函数呢?这应该会起作用。我不建议使用正则表达式处理大型CSV文件。 - piokuc
问题在于使用csv reader会使事情变得复杂。我试图按照csv格式解析文件,但为了获得准确的位置计数,我必须将所有字符相加。我将定期读取文件以查找任何新更改,这就是为什么我想寻找文件离开的位置。是进行运行计数还是将每行保留为原始输入,然后根据csv格式进行处理更好呢? - Legen Diary
好的,在这种情况下,我会在处理时将文件大小(从os.path.getsize获得)保存在某个地方。另一个进程可以在您读取文件时追加到该文件吗? - piokuc
通常不建议使用正则表达式或string.split,但在您的特定情况下,如果数据特别简单(没有带有可能与您的字段分隔符相同的字符串字段),那么这可能是一种方法... - piokuc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接