Стирание части текстового файла в Python - PullRequest
0 голосов
/ 12 сентября 2018

У меня на жестком диске есть текстовый файл, который очень большой. В нем около 8 миллионов файлов 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"}

Ответы [ 2 ]

0 голосов
/ 12 сентября 2018

Поскольку вы хотите, чтобы только последний объект 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()
0 голосов
/ 12 сентября 2018

Самый простой способ - сделать содержимое файла допустимым JSON, заключив его в [ и ], чтобы оно стало списком диктовок, и после удаления последнего элемента из списка вы можете сбросить его обратно в строку, а затем удалите ее первый и последний символы, которые будут [ и ], которые ваш исходный текстовый файл не хочет:

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])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...