【发布时间】: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 "
\ Docstring: getsizeof(object, default) -> int \ 返回对象的字节大小。"是的,上帝,我太笨了,因为我没有直觉,这不会给我我正在看的物体的大小……我怎么会这么笨?!感谢您的反对。 -
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(解决方案)放入问题中,而是将其作为答案发布。
标签: python file io filesize disk