在Python中擦除文本文件的一部分

问题描述 投票:0回答:2

我的硬盘中有一个文本文件非常大。它有大约800万个json文件,用逗号分隔,我想删除最后一个json;但是,因为它非常大,我无法通过常规编辑器(Notepad ++,Sublime,Visual Studio Code,...)来实现。所以,我决定使用Python,但我不知道如何使用python擦除现有文件的一部分。任何形式的帮助将不胜感激。

P.S:我的文件有这样的结构:

json1, json2, json3, ...
when each json looks like {"a":"something", "b":"something", "c":"something"}
python-3.x text text-mining
2个回答
1
投票

最简单的方法是通过用[]封装它来使文件内容有效JSON,这样它就成了一个dicts列表,从列表中删除最后一项后,你可以将它转储回一个字符串然后删除它和最后的字符,将是[],您的原始文本文件不需要:

import json
with open('file.txt', 'r') as r, open('newfile.txt', 'w') as w:
    w.write(json.dumps(json.loads('[%s]' % r.read())[:-1])[1:-1])

1
投票

由于您只希望从文件中删除最后一个JSON对象,因此更有效的方法是在文件末尾标识第一个有效的JSON对象,并从该JSON对象的前一个逗号所在的位置截断该文件。

这可以通过从文件末尾向后搜索和读取来实现,一次一个相对较小的块,通过{拆分缓冲区(因为它标记了JSON对象的开头),并且一次一个地添加片段一个缓冲区,直到缓冲区可以解析为JSON对象(这使得代码能够处理嵌套的dict结构),此时你应该找到前面片段中的前面的逗号并将逗号添加到缓冲区,这样最后,你可以找到缓冲区启动的文件并截断​​文件:

import json
chunk_size = 1024
with open('file.txt', 'rb+') as f:
    f.seek(-chunk_size, 2)
    buffer = ''
    while True:
        fragments = f.read(chunk_size).decode().split('{')
        f.seek(-chunk_size * 2, 1)
        i = len(fragments)
        for fragment in fragments[:0:-1]:
            i -= 1
            buffer = '{%s%s' % (fragment, buffer)
            try:
                json.loads(buffer)
                break
            except ValueError:
                pass
        else:
            buffer = fragments[0] + buffer
            continue
        break
    next_fragment = fragments[i - 1]
    # if we don't have a comma in the preceding fragment and it is already the first
    # fragment, we need to read backwards a little more
    if i == 1 and ',' not in fragments[0]:
        f.seek(-2, 1)
        next_fragment = f.read(2).decode() + next_fragment
    buffer = next_fragment[next_fragment.rindex(','):] + buffer
    f.seek(-len(buffer.encode()), 2)
    f.truncate()
© www.soinside.com 2019 - 2024. All rights reserved.