簡體   English   中英

使用 Python 在大型文本文件中查找和替換特定行的最快方法

[英]Fastest way to find and replace specific line in a large text file with Python

我有一個由 100K 行組成的numbers.txt文件,每行由兩個唯一的數字組成,用:符號分隔:

407597693:1604722326.2426915
510905857:1604722326.2696202
76792361:1604722331.120079
112854912:1604722333.4496727
470822611:1604722335.283259

我的目標是在左側找到一條編號為407597693的行,然后通過向其添加3600來更改右側的編號。 之后,我必須用所有更改重寫numbers.txt文件。 我必須盡快對同一個 txt 文件執行相同(只是數字不同)的操作。

我設法通過with open:文件操作和每行的for循環使其工作,搜索所需的數字,修改行,然后重寫整個文件。 但是,我注意到不斷執行這樣的操作確實需要一些時間來運行我的程序,大約 0.2-0.5 秒,隨着時間的推移它會加起來並大大減慢一切。

這是我正在使用的代碼:

number = 407597693

with open("numbers.txt", "r+") as library:
                file = library.read()
            if (str(number) + ":") in file:
                lines = file.splitlines()
                with open("numbers_temp.txt", "a+") as library_temp:
                    for line in lines:
                        if (str(number) + ":") in line:
                            library_temp.write(
                                "\n" + str(number) + ":" + str(time.time() + 3600)
                            )
                        else:
                            library_temp.write("\n" + line)

                    library_temp.seek(0)
                    new_file = library_temp.read()

                    with open("numbers.txt", "w+") as library_2:
                        library_2.write(new_file)

                os.remove("numbers_temp.txt")

我非常感謝有關如何加快此過程的任何意見,非常感謝!

你可以打開一個內存映射文件,使用正則表達式來找到你想要的行,幸運的話你只需要更改文件中的一頁。 我正在使用十進制模塊,因此您沒有十進制到二進制浮點數轉換問題。 通常新號碼和舊號碼的寬度相同,不需要移動文件內容。 我正在展示一個 linux 示例。 Windows mmap.map有點不同,但應該易於使用。

import mmap
import re
from decimal import Decimal

def increment_record(filename, findval, increment):
    with open(filename, "rb+") as fp:
        with mmap.mmap(fp.fileno(), 0) as fmap:
            search = re.search(rf"{findme}:([\d\.]+)".encode("ascii"), fmap, 
                    re.MULTILINE)
            if search:
                # found float to change. Use Decimal for base 10 precision
                newval = Decimal(search.group(1).decode("ascii")) + increment
                newval = f"{newval}".encode("ascii")
                delta = len(newval) - len(search.group(1))
                if delta:
                    # need to expand file and copy
                    fsize = fmap.size()
                    fmap.resize(fsize + delta)
                    fmap.move(search.end(1) + delta, search.end(1), 
                        fsize - search.end(1))
                # change just the number
                fmap[search.start(1):search.start(1) + len(newval)] = newval

# test parameters
filename = "test.txt"
findme = "76792361"
increment = 3600

testdata = """407597693:1604722326.2426915
510905857:1604722326.2696202
76792361:1604722331.120079
112854912:1604722333.4496727
470822611:1604722335.283259"""

open(filename, "w").write(testdata)

increment_record(filename, findme, increment)

print("changes:")
for old,new in zip(testdata.split("\n"), open(filename)):
    new = new.strip()
    if old != new:
        print((old,new))
print("done")

我假設您的內存可以存儲整個文件。 使用正則表達式應該會更快:

import re
number = 407597693
with open("numbers.txt", "r") as f:
    data = f.read()
    # data = re.sub(f'({number}):(.*)', lambda x:f"{x.group(1)}:{float(x.group(2))+3600}", data)
    data = re.sub("^" + str(number) + ".*\n", str(number) + ":" + str(int(time.time()) + 3600) + "\n", data, flags=re.MULTILINE)
with open("numbers.txt", "w") as f:
    f.write(data)

不必運行多個循環,我們可以在單個循環中執行此操作,如下所示:

number = 407597693
numbers = ''
with open('numbers.txt', "r+") as inputfile:
    file = inputfile.read()

    if(file.find(str(number))) != -1 :
        for line in file.splitlines():
            if (line.find(str(number))) == 0:
                numbers += line.split(':')[0] + ':' + str(float(line.split(':')[1]) + float(3600)) + '\n'
            else:
                numbers += line + '\n'

    with open('numbers.txt', 'w') as updatedFile:
    updatedFile.writelines(numbers)

希望這會有所幫助..

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM