Подтвердить что ты не робот

Самый быстрый способ удалить строку из большого файла в Python

Я работаю с очень большим текстовым файлом (~ 11 ГБ) в системе Linux. Я запускаю его через программу, которая проверяет файл на наличие ошибок. Как только ошибка обнаружена, мне нужно либо исправить строку, либо полностью удалить строку. А затем повторите...

В конце концов, когда мне будет удобно работать с этим процессом, я полностью автоматирую его. Пока же, допустим, я запускаю это вручную.

Каким будет самый быстрый (с точки зрения времени выполнения) способ удаления определенной строки из этого большого файла? Я думал сделать это на Python... но был бы открыт для других примеров. Строка может быть в любом месте файла.

Если Python, предположим следующий интерфейс:

def removeLine(filename, lineno):

Спасибо,

4b9b3361

Ответ 1

Вы можете одновременно иметь два файла для одного и того же файла (один для чтения, один для записи):

def removeLine(filename, lineno):
    fro = open(filename, "rb")

    current_line = 0
    while current_line < lineno:
        fro.readline()
        current_line += 1

    seekpoint = fro.tell()
    frw = open(filename, "r+b")
    frw.seek(seekpoint, 0)

    # read the line we want to discard
    fro.readline()

    # now move the rest of the lines in the file 
    # one line back 
    chars = fro.readline()
    while chars:
        frw.writelines(chars)
        chars = fro.readline()

    fro.close()
    frw.truncate()
    frw.close()

Ответ 2

Измените файл на месте, строка нарушения заменяется пробелами, поэтому оставшуюся часть файла не нужно перетасовывать на диске. Вы также можете "исправить" линию на месте, если исправление не больше, чем строка, которую вы заменяете

import os
from mmap import mmap
def removeLine(filename, lineno):
    f=os.open(filename, os.O_RDWR)
    m=mmap(f,0)
    p=0
    for i in range(lineno-1):
        p=m.find('\n',p)+1
    q=m.find('\n',p)
    m[p:q] = ' '*(q-p)
    os.close(f)

Если другую программу можно изменить для вывода файлового набора вместо номера строки, вы можете напрямую назначить смещение на p и обойтись без цикла цикла

Ответ 3

Насколько я знаю, вы не можете просто открыть txt файл с помощью python и удалить строку. Вы должны создать новый файл и переместить все, кроме этой строки. Если вы знаете конкретную строку, вы бы сделали что-то вроде этого:

f = open('in.txt')
fo = open('out.txt','w')

ind = 1
for line in f:
    if ind != linenumtoremove:
        fo.write(line)
    ind += 1

f.close()
fo.close()

Конечно, вы можете проверить содержимое строки, чтобы определить, хотите ли вы сохранить ее или нет. Я также рекомендую, чтобы, если у вас есть весь список строк, которые нужно удалить/изменить, чтобы сделать все эти изменения за один проход через файл.

Ответ 4

Если строки являются переменной длиной, я не считаю, что есть лучший алгоритм, чем чтение файла по строкам и запись всех строк, за исключением тех, которые вы не хотите.

Вы можете идентифицировать эти строки, проверяя некоторые критерии или сохраняя текущее количество строк, прочитанных и подавляющих запись строк, которые вы не хотите.

Если строки фиксированной длины и вы хотите удалить определенные номера строк, вы можете использовать seek для перемещения указателя файла... Я сомневаюсь, что вам повезло.

Ответ 5

Обновление: решение, использующее sed в соответствии с запросом плаката в комментарии.

Чтобы удалить, например, вторую строку файла:

sed '2d' input.txt

Используйте переключатель -i для редактирования. Предупреждение: это разрушительная операция. Прочтите справку для этой команды для получения информации о том, как сделать резервную копию автоматически.

Ответ 6

def removeLine(filename, lineno):
    in = open(filename)
    out = open(filename + ".new", "w")
    for i, l in enumerate(in, 1):
        if i != lineno:
            out.write(l)
    in.close()
    out.close()
    os.rename(filename + ".new", filename)

Ответ 7

Я думаю, что был несколько схожий, если не совсем тот же вопрос, заданный здесь. Чтение (и запись) по строкам происходит медленно, но вы можете сразу прочитать более крупный фрагмент в памяти, пройти через линию, пропуская строки, которые вы не хотите, а затем записать это как отдельный фрагмент в новый файл. Повторяйте до конца. Наконец, замените исходный файл на новый файл.

Вещь, о которой следует помнить, - это когда вы читаете в куске, вам нужно иметь дело с последней, потенциально частичной линией, которую вы читаете, и добавить в следующий фрагмент, который вы читаете.

Ответ 8

@OP, если вы можете использовать awk, например, если номер строки равен 10

$ awk 'NR!=10' file > newfile

Ответ 9

Я предоставлю две альтернативы на основе коэффициента поиска (номер строки или строки поиска):

Номер строки

def removeLine2(filename, lineNumber):
    with open(filename, 'r+') as outputFile:
        with open(filename, 'r') as inputFile:

            currentLineNumber = 0 
            while currentLineNumber < lineNumber:
                inputFile.readline()
                currentLineNumber += 1

            seekPosition = inputFile.tell()
            outputFile.seek(seekPosition, 0)

            inputFile.readline()

            currentLine = inputFile.readline()
            while currentLine:
                outputFile.writelines(currentLine)
                currentLine = inputFile.readline()

        outputFile.truncate()

Строка

def removeLine(filename, key):
    with open(filename, 'r+') as outputFile:
        with open(filename, 'r') as inputFile:
            seekPosition = 0 
            currentLine = inputFile.readline()
            while not currentLine.strip().startswith('"%s"' % key):
                seekPosition = inputFile.tell()
                currentLine = inputFile.readline()

            outputFile.seek(seekPosition, 0)

            currentLine = inputFile.readline()
            while currentLine:
                outputFile.writelines(currentLine)
                currentLine = inputFile.readline()

        outputFile.truncate()