估计文件中的行数 - 文件大小和所有行的大小不匹配
Posted
技术标签:
【中文标题】估计文件中的行数 - 文件大小和所有行的大小不匹配【英文标题】:estimating number of lines in a file - mismatch between file size and size of all lines 【发布时间】:2015-02-22 21:52:33 【问题描述】:我有几百个文件,每个文件的大小在 10 到几 GB 之间,我想估计行数(即不需要精确计数)。每行都非常规则,例如 4 个长整数和 5 个双浮点数。
我试图找出文件中前AVE_OVER
行的平均大小,然后用它来估计总行数:
nums = sum(1 for line in open(files[0]))
print "Number of lines = ", nums
AVE_OVER = 10
lineSize = 0.0
count = 0
for line in open(files[0]):
lineSize += sys.getsizeof(line)
count += 1
if( count >= AVE_OVER ): break
lineSize /= count
fileSize = os.path.getsize(files[0])
numLines = fileSize/lineSize
print "Estimated number of lines = ", numLines
估计差远了:
> Number of lines = 505235
> Estimated number of lines = 324604.165863
所以我尝试计算文件中所有行的总大小,与sys
测量的大小相比:
fileSize = os.path.getsize(files[0])
totalLineSize = 0.0
for line in open(files[0]):
totalLineSize += sys.getsizeof(line)
print "File size = %.3e" % (fileSize)
print "Total Line Size = %.3e" % (totalLineSize)
但这些又是不一致的!
> File size = 3.366e+07
> Total Line Size = 5.236e+07
为什么每行的大小总和比实际的总文件大小大得多?我该如何纠正这个问题?
编辑:我最终得到的算法(2.0版);感谢@J.F.Sebastian
def estimateLines(files):
""" Estimate the number of lines in the given file(s) """
if( not np.iterable(files) ): files = [files]
LEARN_SIZE = 8192
# Get total size of all files
numLines = sum( os.path.getsize(fil) for fil in files )
with open(files[0], 'rb') as file:
buf = file.read(LEARN_SIZE)
numLines /= (len(buf) // buf.count(b'\n'))
return numLines
【问题讨论】:
@OlehPrypin "line.count(b'\n')
是 1
(如果文件末尾没有换行符,则为 0
)。不要一起使用for line in file
和line.count(b'\n')
:没用。使用其中一种。后者更快。 def estimateLines(filename): return os.path.getsize(filename) // line_size_hint(filename)
@J.F.Sebastian 感谢您的反馈。我试图在前几行上实现平均值 --- 但现在我知道你的已经这样做了(嗯,最多 8192 字节)。
如果您想避免估计每个文件的行大小并使用基于第一个文件计算的行大小提示然后估计多个文件中的行数,您可以使用numLines = sum(map(os.path.getsize, files)) // line_size_hint(files[0])
。
1) 删除if not np.iterable(files): files = [files]
。它什么也不做,因为 str
/unicode
实例是可迭代的(在 Python 2 中 open()
可以接受的类型)。您是否期望一个不可迭代但被open()
接受的(缓冲区)类型? 2) 使用//=
与 Python 3 兼容。3) 为什么不想将代码片段重构为 line_size_hint()
函数(函数调用开销应该与所有 I/O 相比可以忽略不计)? 4) 不要将answer(解决方案)放入问题中,而是将其作为答案发布。
【参考方案1】:
要估计文件中的行数:
def line_size_hint(filename, learn_size=1<<13):
with open(filename, 'rb') as file:
buf = file.read(learn_size)
return len(buf) // buf.count(b'\n')
number_of_lines_approx = os.path.getsize(filename) // line_size_hint(filename)
要查找确切的行数,您可以use wc-l.py
script:
#!/usr/bin/env python
import sys
from functools import partial
print(sum(chunk.count('\n') for chunk in iter(partial(sys.stdin.read, 1 << 15), '')))
【讨论】:
【参考方案2】:sys.getsizeof
是这里出现问题的唯一原因。它给出了依赖于实现的任意大小的对象,根本不应该使用,除了极少数情况。
只需将文件作为二进制文件打开,然后使用 len
获取行的实际长度。
【讨论】:
以上是关于估计文件中的行数 - 文件大小和所有行的大小不匹配的主要内容,如果未能解决你的问题,请参考以下文章