【问题标题】:Replace Single Character in a line of a Text file with Python用 Python 替换文本文件的一行中的单个字符
【发布时间】:2018-07-09 20:05:04
【问题描述】:

我有一个文本文件,其中所有文件当前都具有相同的结束字符 (N),用于识别系统取得的进展。我想将结束字符更改为“Y”,以防程序因错误或其他中断而结束,以便在重新启动程序时搜索直到一行具有结束字符“N”并从那里开始工作。以下是我的代码以及文本文件中的示例。

更新代码:

def GeoCode():
    f = open("geocodeLongLat.txt", "a")
    with open("CstoGC.txt",'r') as file:
        print("Geocoding...")
        new_lines = []
        for line in file.readlines():
            check = line.split('~')
            print(check)
            if 'N' in check[-1]:
                geolocator = Nominatim()
                dot_number, entry_name, PHY_STREET,PHY_CITY,PHY_STATE,PHY_ZIP = check[0],check[1],check[2],check[3],check[4],check[5] 
                address = PHY_STREET + " " + PHY_CITY + " " + PHY_STATE + " " + PHY_ZIP
                f.write(dot_number + '\n')
                try:
                    location = geolocator.geocode(address)
                    f.write(dot_number + "," + entry_name + "," + str(location.longitude) + "," + str(location.latitude) + "\n")
                except AttributeError:
                    try:
                        address = PHY_CITY + " " + PHY_STATE + " " + PHY_ZIP
                        location = geolocator.geocode(address)
                        f.write(dot_number + "," + entry_name + "," + str(location.longitude) + "," + str(location.latitude) + "\n")
                    except AttributeError:
                        print("Cannot Geocode")
            check[-1] = check[-1].replace('N','Y')
        new_lines.append('~'.join(check))

    with open('CstoGC.txt','r+') as file: # IMPORTANT to open as 'r+' mode as 'w/w+' will truncate your file!
        for line in new_lines:
            file.writelines(line)        

    f.close()

输出:

2967377~DARIN COLE~22112 TWP RD 209~ALVADA~OH~44802~Y
WAY 64 SUITE 100~EADS~TN~38028~N
384767~MILLER FARMS TRANS LLC~1103 COURT ST~BEDFORD~IA~50833~N
986150~R G S TRUCKING LTD~1765 LOMBARDIE DRIVE~QUESNEL~BC~V2J 4A8~N
1012987~DONALD LARRY KIVETT~4509 LANSBURY RD~GREENSBORO~NC~27406-4509~N
735308~ALZEY EXPRESS INC~2244  SOUTH GREEN STREET~HENDERSON~KY~42420~N
870337~RIES FARMS~1613 255TH AVENUE~EARLVILLE~IA~52057~N
148428~P R MASON & SON LLC~HWY 70 EAST~WILLISTON~NC~28589~N
220940~TEXAS MOVING CO INC~908 N BOWSER RD~RICHARDSON~TX~75081-2869~N
854042~ARMANDO ORTEGA~6590 CHERIMOYA AVENUE~FONTANA~CA~92337~N
940587~DIAMOND A TRUCKING INC~192285 E COUNTY ROAD 55~HARMON~OK~73832~N
1032455~INTEGRITY EXPRESS LLC~380 OLMSTEAD AVENUE~DEPEW~NY~14043~N
889931~DUNSON INC~33 CR 3581~FLORA VISTA~NM~87415~N
143608~LARRY A PETERSON & DONNA M PETERSON~W6359 450TH AVE~ELLSWORTH~WI~54011~N
635528~JAMES E WEBB~3926 GREEN ROAD~SPRINGFIELD~TN~37172~N
805496~WAYNE MLADY~22272 135TH ST~CRESCO~IA~52136~N
704996~SAVINA C MUNIZ~814 W LA QUINTA DR~PHARR~TX~78577~N
893169~BINDEWALD MAINTENANCE INC~213 CAMDEN DR~SLIDELL~LA~70459~N
948130~LOGISTICIZE LTD~861 E PERRY ST~PAULDING~OH~45879~N
438760~SMOOTH OPERATORS INC~W8861 CREEK ROAD~DARIEN~WI~53114~N
518872~A B C RELOCATION SERVICES INC~12 BOCKES ROAD~HUDSON~NH~03051~N
576143~E B D ENTERPRISES INC~29 ROY ROCHE DRIVE~WINNIPEG~MB~R3C 2E6~N
968264~BRIAN REDDEMANN~706 WESTGOR STREET~STORDEN~MN~56174-0220~N
721468~QUALITY LOGISTICS INC~645 LEONARD RD~DUNCAN~SC~29334~N

如您所见,我已经通过使用 x 来跟踪我所在的行。我应该使用类似 file.readlines() 的东西吗?

文本文档示例:

570772~CORPORATE BANK TRANSIT OF KENTUCKY INC~3157 HIGHWAY 64 SUITE 100~EADS~TN~38028~N
384767~MILLER FARMS TRANS LLC~1103 COURT ST~BEDFORD~IA~50833~N
986150~R G S TRUCKING LTD~1765 LOMBARDIE DRIVE~QUESNEL~BC~V2J 4A8~N
1012987~DONALD LARRY KIVETT~4509 LANSBURY RD~GREENSBORO~NC~27406-4509~N
735308~ALZEY EXPRESS INC~2244  SOUTH GREEN STREET~HENDERSON~KY~42420~N
870337~RIES FARMS~1613 255TH AVENUE~EARLVILLE~IA~52057~N
148428~P R MASON & SON LLC~HWY 70 EAST~WILLISTON~NC~28589~N
220940~TEXAS MOVING CO INC~908 N BOWSER RD~RICHARDSON~TX~75081-2869~N
854042~ARMANDO ORTEGA~6590 CHERIMOYA AVENUE~FONTANA~CA~92337~N
940587~DIAMOND A TRUCKING INC~192285 E COUNTY ROAD 55~HARMON~OK~73832~N
1032455~INTEGRITY EXPRESS LLC~380 OLMSTEAD AVENUE~DEPEW~NY~14043~N
889931~DUNSON INC~33 CR 3581~FLORA VISTA~NM~87415~N

谢谢!

编辑:感谢@idlehands 更新代码

【问题讨论】:

  • 如果你使用 str.format(),你可以获得很多可读性。阅读它,这是值得的:)
  • 这是一个相当广泛的问题。最好阅读file methods 并尝试一些事情。您可能正在寻找类似zipf.readlines() 和范围对象的东西。你现在拥有的也应该可以正常工作。
  • 您不能替换打开的文件中的任何内容以进行附加。你也看不懂。
  • 另外你说的是一个文件,但你的代码使用了两个。
  • @Goyo,一个文件只是添加了经度和纬度

标签: python python-3.x file text


【解决方案1】:

我会将整个输入文件读入一个列表,然后 .pop() 一次删除一行。如果出现错误,将弹出的项目附加到列表并覆盖输入文件。这样一来,它将始终是最新的,您不需要任何其他逻辑。

【讨论】:

    【解决方案2】:

    有几种方法可以做到这一点。

    选项#1

    我最初的想法是使用tell()seek() 方法返回几个步骤,但它很快表明,当您不在bytes 中打开文件并且绝对不是在for 循环的 readlines()。您可以在此处查看参考线程:

    Is it possible to modify lines in a file in-place?
    How to solve "OSError: telling position disabled by next() call"

    调查导致了这段代码:

    with open('file.txt','rb+') as file:
        line = file.readline() # initiate the loop
        while line: # continue while line is not None
            print(line)
            check = line.split(b'~')[-1]
            if check.startswith(b'N'): # carriage return is expected for each line, strip it
    
                # ... do stuff ... #
    
                file.seek(-len(check), 1) # place the buffer at the check point
                file.write(check.replace(b'N', b'Y')) # replace "N" with "Y"
            line = file.readline() # read next line
    

    在第一个引用的线程中,提到的其中一个答案可能会导致您出现潜在问题,并且在读取缓冲区时直接修改缓冲区上的字节可能被认为是一个坏主意™。很多专业人士可能会因为我的建议而责骂我。

    选项 #2a

    (如果文件大小不是特别大)

    with open('file.txt','r') as file:
        new_lines = []
        for line in file.readlines():
            check = line.split('~')
            if 'N' in check[-1]:
    
                # ... do stuff ... #
    
                check[-1] = check[-1].replace('N','Y')
            new_lines.append('~'.join(check))
    
    with open('file.txt','r+') as file: # IMPORTANT to open as 'r+' mode as 'w/w+' will truncate your file!
        for line in new_lines:
            file.writelines(line)
    

    这种方法首先将所有行加载到内存中,因此您在内存中进行修改,但不理会缓冲区。然后您重新加载文件并写入已更改的行。需要注意的是,从技术上讲,您正在逐行重写整个文件 - 而不仅仅是字符串 N,即使它是唯一更改的内容。

    选项 #2b

    从技术上讲,您可以从一开始就以r+ 模式打开文件,然后在迭代完成后执行此操作(仍在with 块内但在循环之外):

    # ... new_lines.append('~'.join(check)) #
        file.seek(0)
        for line in new_lines: 
            file.writelines(line)
    

    我不确定这与选项 #1 有何区别,因为您仍在同时读取和修改文件。如果有更精通 IO/缓冲区/内存管理的人想插话。

    选项 2a/b 的缺点是,即使您只剩下几行需要从“N”更新为“Y”,您总是最终会存储和重写文件中的行。

    结果(适用于所有解决方案):

    570772~CORPORATE BANK TRANSIT OF KENTUCKY INC~3157 HIGHWAY 64 SUITE 100~EADS~TN~38028~Y
    384767~MILLER FARMS TRANS LLC~1103 COURT ST~BEDFORD~IA~50833~Y
    986150~R G S TRUCKING LTD~1765 LOMBARDIE DRIVE~QUESNEL~BC~V2J 4A8~Y
    1012987~DONALD LARRY KIVETT~4509 LANSBURY RD~GREENSBORO~NC~27406-4509~Y
    735308~ALZEY EXPRESS INC~2244  SOUTH GREEN STREET~HENDERSON~KY~42420~Y
    870337~RIES FARMS~1613 255TH AVENUE~EARLVILLE~IA~52057~Y
    148428~P R MASON & SON LLC~HWY 70 EAST~WILLISTON~NC~28589~Y
    220940~TEXAS MOVING CO INC~908 N BOWSER RD~RICHARDSON~TX~75081-2869~Y
    854042~ARMANDO ORTEGA~6590 CHERIMOYA AVENUE~FONTANA~CA~92337~Y
    940587~DIAMOND A TRUCKING INC~192285 E COUNTY ROAD 55~HARMON~OK~73832~Y
    1032455~INTEGRITY EXPRESS LLC~380 OLMSTEAD AVENUE~DEPEW~NY~14043~Y
    889931~DUNSON INC~33 CR 3581~FLORA VISTA~NM~87415~Y
    

    如果你说,在以220940 开头的行遇到中断,文件将变为:

    570772~CORPORATE BANK TRANSIT OF KENTUCKY INC~3157 HIGHWAY 64 SUITE 100~EADS~TN~38028~Y
    384767~MILLER FARMS TRANS LLC~1103 COURT ST~BEDFORD~IA~50833~Y
    986150~R G S TRUCKING LTD~1765 LOMBARDIE DRIVE~QUESNEL~BC~V2J 4A8~Y
    1012987~DONALD LARRY KIVETT~4509 LANSBURY RD~GREENSBORO~NC~27406-4509~Y
    735308~ALZEY EXPRESS INC~2244  SOUTH GREEN STREET~HENDERSON~KY~42420~Y
    870337~RIES FARMS~1613 255TH AVENUE~EARLVILLE~IA~52057~Y
    148428~P R MASON & SON LLC~HWY 70 EAST~WILLISTON~NC~28589~Y
    220940~TEXAS MOVING CO INC~908 N BOWSER RD~RICHARDSON~TX~75081-2869~N
    854042~ARMANDO ORTEGA~6590 CHERIMOYA AVENUE~FONTANA~CA~92337~N
    940587~DIAMOND A TRUCKING INC~192285 E COUNTY ROAD 55~HARMON~OK~73832~N
    1032455~INTEGRITY EXPRESS LLC~380 OLMSTEAD AVENUE~DEPEW~NY~14043~N
    889931~DUNSON INC~33 CR 3581~FLORA VISTA~NM~87415~N
    

    这些方法各有利弊。试试看哪一个最适合您的用例。

    【讨论】:

    • 我尝试执行您的选项 2a,但它根本没有编辑文本文档
    • 你是如何实现它的?对我来说效果很好。
    • new_lines.append('~'.join(check)) 缩进一级。它应该在您的 if 'N' in check[-1]: 条件之外但在您的 for 循环内,以便无论是否满足条件,它都会附加该行。
    • 不确定发生了什么。我的 GeoCode 出现超时错误(我正在谈论的中断)并且文本文件仍然是错误的。我认为在处理/地理编码后将一个字符附加到每个条目的末尾可能会更容易,并且每次只需检查该结束字符。
    • 这听起来似乎很简单,但您确实在f.close() 之后将new_lines 写回了您的文件......对吗?此外,如果您的代码抛出错误(未处理)当然它不会工作,因为文件尚未关闭。仔细检查我的代码,看看你是否没有错过复制任何内容。
    猜你喜欢
    • 2021-06-12
    • 1970-01-01
    • 2012-11-06
    • 2016-03-29
    • 1970-01-01
    • 2018-05-19
    • 2015-07-11
    • 2023-03-25
    • 2019-12-01
    相关资源
    最近更新 更多