读取非常大的一行文本文件

Reading Very Large One Liner Text File

我有一个 30MB 的 .txt 文件,有 一行 行数据 (3000 万位数)
不幸的是,我尝试过的每种方法(mmap.read()readline()、分配 1GB RAM、用于循环)都需要 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

除了将数字从一行拆分为多行;我不想这样做,有没有更简洁的方法不需要一个小时的大部分时间?

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

我有:Windows8.1 64 位,16GB 内存,Python3.5.1

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

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

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

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

但是,将这 30 MB 转换为整数是您的瓶颈, 因为 python 无法用 long 数据类型表示。

你可以试试 Decimal 模块,不过它主要是为浮点运算设计的。

除此之外,当然还有 numpy,它可能会更快(并且由于您稍后可能想对数字进行一些处理,因此使用这样的库是有意义的)。

文件读取速度快(<1s):

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

将 3000 万位的字符串转换为整数,速度很慢:

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

如果您将数字存储为原始大端或小端二进制数据,那么 int.from_bytes(data,'big') 会快得多。

如果我算对了(注意 _ 在 Python 的交互式解释器中表示 "last line's answer"):

>>> 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 票 :^)

我使用 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 秒内完成,慢得多,但至少它给了我一个整数值。

谢谢大家宝贵的回答,不过我会尽快标记这个。