如何追加一个二进制文件?

0 投票
2 回答
2468 浏览
提问于 2025-04-18 04:33

这个问题和Project Euler的第10题有关:计算低于两百万的所有质数的总和。在我找到正确的算法之前,程序运行得非常慢,所以我决定把找到的质数分批写入一个数据文件。现在我有了正确的主算法,但我想知道如何在数据文件中追加内容。

#Project Euler 10a: list primes below 2,000,000.

import pickle

def numprime(x):
    for i in range(2, int(x**0.5)+1):
        if x % i == 0:
            return False
    else:
        return True

def growfile(primes, faccess):
    file = open('primelist2kk.dat', faccess)
    pickle.dump(primes, file)
    file.close()

def main(fchunk, faccess):
    #File input broken up for memory
    for i in range(10):
        plist = []
        for j in range(1, fchunk, 2):
            k = fchunk*i + j
            if numprime(k):
                plist.append(k)
        if i == 0:
            plist.pop(0)
            plist.insert(0,2)
        print()
        print(plist)
        growfile(plist, faccess)

def viewfile(faccess):
    g = open('primelist2kk.dat', faccess)  
    h = pickle.load(g)
    g.close()
    print(h)
    g.closed


#Supply 1/10 of the prime upper bound
#main(200, 'ab')
viewfile('rb')

我尝试了各种合理的文件访问代码组合,但都没有成功。要么后面的数据块覆盖了第一个,要么根本没有保存。有没有什么好主意?

注意:取消注释main()以创建文件并显示程序输出。注释掉main(),然后取消注释viewfile()以查看文件。

2 个回答

0

你需要使用追加模式,也就是这样。

faccess = 'ab'

顺便提一下,埃拉托斯特尼筛法是一种更快生成质数的方法。

这是筛法的一个例子。

N = range(2000000)
P = []
for i in N:
    if i > 1:
        P.append(i)
        N[::i] = [0]*((len(N)+i-1)//i)

print P
3

你需要用追加模式来更新你的文件(ab),但这还不够。每次用 pickle.dump 写入的二进制数据块都是独立的。当你用 pickle.load 从打开的文件中读取时,只能得到第一个数据块。你需要用循环不断读取数据,直到没有更多的数据为止。

def viewfile():
    with open('primelist2kk.dat', 'rb') as g:
        try:
            while True: # run until there's an exception
                h = pickle.load(g)
                print(h)
        except EOFError: # this will be raised by load() when there's no more data
            pass

如果你不想让每个数据块单独打印出来,你可以把它们放在一个列表里一起处理。

撰写回答