【问题标题】:suggestion required related to rewriting and string manipulation需要与重写和字符串操作相关的建议
【发布时间】:2009-12-17 19:34:12
【问题描述】:

我必须从文件中读取,对于分隔符之间的每个数据,我需要删除空格,并且我在 jython 中编写了以下程序

当我尝试重写时,它会在源文件的末尾进行重写。

filesrc = open('c:/FILE/split_doc.txt','r+')
for list in filesrc.readlines():
    #split the records by the delimiter
    fields = list.split(',')
    list = ",".join([s.strip() for s in fields])
    filesrc.writelines(list+"\n")

filesrc.close()

所以我做了一些修改并添加了 file.seek,这样我就可以在源代码行上重写,它在一定程度上起作用,除了它在末尾添加了两行额外的行,这意味着查找部分存在问题。

修改后的程序是

filesrc = open('c:/ODI_FILE/split_doc.txt','r+')
lines=0
for list in filesrc.readlines():
    #split the records by the delimiter
        fields = list.split(',')
    list = ",".join([s.strip() for s in fields])
    filesrc.seek(lines)
    filesrc.writelines(list+"\n")
    lines += len(list+"\n")

filesrc.close()

请帮助我正确的逻辑。

带有多余空格的正确源文件

52       ,William   ,Kudo       ,28/03/199300:00:00
11,Andrew,      Andersen,22/02/199900:00:00
12,John        ,Galagers,20/04/200000:00:00
13,Jeffrey        ,Jeferson,10/06/198800:00:00
20,Jennie,Daumesnil,28/02/198800:00:00
21,Steve,Barrot,24/09/199200:00:00
22,Mary,Carlin,14/03/199500:00:00
30,Paul,Moore,11/03/199900:00:00

这是我的错误输出

52,William,Kudo,28/03/199300:00:00
11,Andrew,Andersen,22/02/199900:00:00
12,John,Galagers,20/04/200000:00:00
13,Jeffrey,Jeferson,10/06/198800:00:00
20,Jennie,Daumesnil,28/02/198800:00:00
21,Steve,Barrot,24/09/199200:00:00
22,Mary,Carlin,14/03/199500:00:00
30,Paul,Moore,11/03/199900:00:00
9500:00:00
30,Paul,Moore,11/03/199900:00:00

这里最后两行不应该出现

请建议所需且更快的方法,因为这是一个示例文件,我必须让该程序适用于数百万行。

有没有办法让这个逻辑也适用于 while 循环?

【问题讨论】:

  • 尽量避免使用像“list”这样的变量名,因为它们会影响内置类型。在这种情况下,它无论如何都不是一个列表。我会使用“for line in...”,因为它正确地反映了内容。

标签: python file rewrite jython


【解决方案1】:

您不想在阅读时写入同一个文件。这在技术上是可行的,但这条路充满了麻烦和痛苦。

这是您应该遵循的简单明了的过程:

  • 将整个文件读入字符串然后关闭文件
  • 将换行符上的字符串拆分成一个列表
  • 处理每一行以去除多余的间距
  • 将列表重新加入字符串
  • 用新清理的数据覆盖源文件

如果您不想一次将整个文件加载到内存中,请尝试以下过程:

  • 打开文件进行阅读
  • 逐行阅读
  • 将清理后的行写入新的临时输出文件
  • 写完所有行后,删除原文件
  • 将临时文件重命名为原始名称

我的建议是两种方式都写,看看什么可行或不可行,哪种方式更快,而不是仅仅因为它有数百万行就假设你不能将它全部读入内存。也许它会工作得很好。

此外,您当然也可以使用 while 循环来完成这项工作。为此,您需要以 while 循环的形式阅读 Python 文档并进行一些实验。您如何编写该循环将取决于您如何加载文件:一次全部放入一个字符串,然后拆分为一个列表,或者直接从文件中逐行。对于任何一种情况,你怎么知道 while 循环需要做多少工作,你将如何从一个工作推进到下一个工作,你怎么知道它什么时候完成?如果你能回答这些问题,你就可以编写你的循环了。

【讨论】:

  • 感谢您的建议,我将尝试解决方法
【解决方案2】:

您在进行过程中进行覆盖,但最终结果比原始结果短,因此您会得到原始版本的最后 X 个字符,其中 X 是原始版本与新版本之间的大小差异。此版本中额外的 .seek() 和 truncate() 调用将搜索到新输出的末尾并切断文件的其余部分。

filesrc = open('c:/ODI_FILE/split_doc.txt','r+')
lines=0
for list in filesrc.readlines():
    #split the records by the delimiter
        fields = list.split(',')
    list = ",".join([s.strip() for s in fields])
    filesrc.seek(lines)
    filesrc.writelines(list+"\n")
    lines += len(list+"\n")
filesrc.seek(lines)
filesrc.truncate()
filesrc.close()

【讨论】:

  • 非常感谢它的工作。我现在面临另一个问题,在处理 500,000 行时出现 java 内存不足错误,我已更改为 512mx 但仍然失败。当我使用它工作的while循环时,我实际上在将for循环与另一个程序一起使用时遇到了同样的问题。是否可以更改while循环的程序,再次感谢您的及时帮助
  • readlines() 会将整个内容读入内存中的列表。使用迭代器的问题是您在同一个文件中查找(),我怀疑这会导致迭代器出现问题。要使用 while 循环,您需要两个指向文件的指针并在它们之间查找。从一个文件读取并写入另一个文件是否可行?这将简化您的任务。
  • 最初我确实写入了另一个文件,但后来我意识到我的要求主要是使用即将到来的相同文件名,我无法更改文件名,所以我必须阅读和写入同一个文件。
  • 您不需要读取和写入同一个文件。正如其他人指出的那样,这是危险的。考虑一下如果停电会发生什么。不要将整个文件读入内存。重命名旧文件以具有包含时间戳、读取旧文件、写入/刷新/关闭新文件的名称。当您确定不再需要备份文件时,稍后再删除它。
  • 当您没有将整个文件读入内存时,可能存在覆盖同一个文件的危险(读取下一个块会为您提供上一次迭代的一些新版本),所以其中任何一个改进可能是危险的,但是两者都这样做无疑是一种更好的方法。一次操作一个块,输出到一个新文件,然后将新文件复制到旧文件的位置。
【解决方案3】:

这并不能回答您的问题,但您是否考虑过不使用 jython 执行此操作?

试过Sed

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-24
    • 1970-01-01
    • 2011-01-07
    • 1970-01-01
    • 1970-01-01
    • 2018-03-12
    • 2012-04-06
    • 1970-01-01
    相关资源
    最近更新 更多