当文件句柄存储在Dict中时,为什么使用“w+”而不是“a+”会在文件中产生垃圾?

2024-10-02 02:37:00 发布

您现在位置:Python中文网/ 问答频道 /正文

我编写了一个函数,它接受一个包含多个字段的项目列表,并根据某些字段的内容将每个项目写入一个或多个文件。你知道吗

文件的名称基于这些字段的内容,因此例如,字段rating中具有值AAA的项和字段country中具有值Spain的项将结束于文件AAA_firms.txtSpain_firms.txtSpain_AAA_firms.txt(只是一个示例,不是真实情况)。你知道吗

当我第一次对它进行编码时,我使用'w+'作为打开文件的模式,得到的结果是文件的大部分内容似乎都已损坏,^@是我在文件中的字符,文件末尾只有几个正确的条目。例如,我们正在讨论一个超过3500个条目的文件,其末尾只有不到100个条目是可阅读的,文件的其余部分是^@字符。你知道吗

我找不到原因,所以我用另一种方法做了它,我把所有的条目都存储在dict的列表中,然后一次将每个列表写到一个文件中,再次用w+打开文件,这样做很好,但我对发生的事很好奇。你知道吗

除此之外,我还尝试将'w+'更改为'a+',这很有效!你知道吗

我想知道使'w+'工作不稳定和'a+'工作正常的确切区别。你知道吗

我将下面的代码的模式设置为'w+'(这样它会将看似垃圾的内容写入文件)。你知道吗

代码不是100%真实的,我必须修改名称并且是类的一部分(源代码列表本身,实际上是一个dict包装器,您可以从这里的代码猜到)。你知道吗

def extractLists(self, outputDir, filenameprefix):
    totalEntries = 0
    aKey = "rating"
    bKey = "country"
    nameKey = "name"
    representativeChars = 2
    fileBase = outputDir + "/" + filenameprefix
    filenameAll = fileBase + "_ALL.txt"

    xLists = dict()

    for item in self.content.values():
        if (item[aKey] != aKey):
            totalEntries = totalEntries + 1
            filenameA = fileBase + "_" + item[aKey]+ "_ANY.txt"
            filenameB = fileBase + "_ANY_" + item[bKey][0:representativeBuildingChars]+ ".txt"
            filenameAB = fileBase + "_" + item[aKey]+ "_" + item[bKey][0:representativeBuildingChars] + ".txt" 
            xLists.setdefault(filenameAll,open(filenameAll,"w+")).write(item[nameKey]+"\n")
            mailLists.setdefault(filenameA,open(filenameA,"w+")).write(item[nameKey]+"\n")
            mailLists.setdefault(filenameB,open(filenameB,"w+")).write(item[nameKey]+"\n")
            mailLists.setdefault(filenameAB,open(filenameAB,"w+")).write(item[nameKey]+"\n")

    for fileHandle in mailLists.values():
        fileHandle.close()

    print(totalEntries)  
    return totalEntries

Tags: 文件txt内容列表openitemwriteaaa
1条回答
网友
1楼 · 发布于 2024-10-02 02:37:00

每次循环中都要重新打开文件对象,即使已经存在于字典中。表达式:

mailLists.setdefault(filenameA,open(filenameA,"w+"))

首先打开文件,因为setdefault()的两个参数都需要可用。使用open(..., 'w+')截断文件。你知道吗

当您第一次这样做时,文件名还没有出现,但是在以后的所有时间里,您只是截断了一个仍然有打开的文件句柄的文件。字典中已经存在的打开文件句柄具有文件写入位置,并从该位置继续写入。由于文件刚刚被截断,这将导致您观察到的行为:文件内容已损坏。您将看到多个条目被写入,因为数据仍然可以被缓冲;只有已经刷新到磁盘的数据会丢失。你知道吗

请看这个简短的演示(在OSX上执行,不同的操作系统和文件系统的行为可能不同):

>>> with open('/tmp/testfile.txt', 'w') as f:
...     f.write('The quick brown fox')
...     f.flush()  # flush the buffer to disk
...     open('/tmp/testfile.txt', 'w')  # second open call, truncates
...     f.write(' jumps over the lazy fox')
...
<open file '/tmp/testfile.txt', mode 'w' at 0x10079b150>
>>> with open('/tmp/testfile.txt', 'r') as f:
...     f.read()
...
'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 jumps over the lazy fox'

aappend模式下打开文件不会截断,这就是为什么这种更改会起作用。你知道吗

不要一直打开文件,只在文件实际丢失时才打开。您必须使用if语句:

if filenameA not in mailLists:
    mailLists[filenameA] = open(filenameA, 'w+')

我不知道你为什么在filemode中使用+,因为你看起来没有从任何文件中读取。你知道吗

对于filenameAll,变量名永远不会更改,您根本不需要在循环中打开该文件。把这个移到外,只打开一次。你知道吗

相关问题 更多 >

    热门问题