繁体   English   中英

阅读非常大的一个班轮文本文件

[英]Reading Very Large One Liner Text File

我有一个30MB .txt文件,与数据的一行 (30百万位数字)
不幸的是,我尝试的每个方法( mmap.read()readline() ,分配1GB的RAM,for循环)需要45分钟才能完全读取文件。 我在互联网上找到的每一种方法似乎都是因为每条线都很小,因此内存消耗量只有文件中的最大线。 这是我一直在使用的代码。

start = time.clock()
z = open('Number.txt','r+') 
m = mmap.mmap(z.fileno(), 0)
global a
a = int(m.read())
z.close()
end = time.clock()
secs = (end - start)
print("Number read in","%s" % (secs),"seconds.", file=f)
print("Number read in","%s" % (secs),"seconds.")
f.flush()
del end,start,secs,z,m

除了将数字从一行分成不同的行; 我宁愿不这样做,是否有一种更清洁的方法,不需要一小时的大部分时间?

顺便说一句,我不一定要使用文本文件。

我有:Windows 8.1 64位,16GB RAM,Python 3.5.1

读取的文件很快(<1s):

with open('number.txt') as f:
    data = f.read()

将一个3000万字节的字符串转换为整数,这很慢:

z=int(data) # still waiting...

如果将数字存储为原始的big或little-endian二进制数据,则int.from_bytes(data,'big')要快得多。

如果我的数学运算正确(注意_表示Python的交互式解释器中的“最后一行答案”):

>>> import math
>>> math.log(10)/math.log(2)  # Number of bits to represent a base 10 digit.
3.3219280948873626
>>> 30000000*_                # Number of bits to represent 30M-digit #.
99657842.84662087
>>> _/8                       # Number of bytes to represent 30M-digit #.
12457230.35582761             # Only ~12MB so file will be smaller :^)
>>> import os
>>> data=os.urandom(12457231) # Generate some random bytes
>>> z=int.from_bytes(data,'big')  # Convert to integer (<1s)
99657848
>>> math.log10(z)   # number of base-10 digits in number.
30000001.50818886

编辑 :仅供参考,我的数学不对,但我修好了。 感谢10个赞成票而没有注意到:^)

一个30MB的文本文件不应该花很长时间阅读,现代硬盘驱动器应该能够在不到一秒的时间内完成(不计入访问时间)

在这种情况下,使用标准的python文件IO应该可以正常工作:

with open('my_file', 'r') as handle:
    content = handle.read()

在我的笔记本电脑上使用它可以产生不到一秒的时间。

但是,将这30 MB转换为整数是你的瓶颈,因为python不能用long数据类型来表示它。

您可以尝试使用Decimal模块,但它主要用于浮点运算。

除此之外,当然还有numpy,它可能更快(因为你可能想稍后使用这个数字进行一些工作,所以使用这样的库是有意义的)。

我使用gmpy2模块将字符串转换为数字。

start = time.clock()  
z=open('Number.txt','r+') 
data=z.read()
global a
a=gmpy2.mpz(data)
end = time.clock()
secs = (end - start)
print("Number read in","%s" % (secs),"seconds.", file=f)
print("Number read in","%s" % (secs),"seconds.")
f.flush()
del end,secs,start,z,data

它在3秒内工作,慢得多,但至少它给了我一个整数值。

谢谢大家的宝贵答案,但我会尽快给你留下这个答案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM