【问题标题】:How do I split one file into two files using Python? [closed]如何使用 Python 将一个文件拆分为两个文件? [关闭]
【发布时间】:2012-06-13 18:17:28
【问题描述】:

我有一个文件,其中包含一些代码行,后跟一个字符串模式。我需要在文件一中包含字符串模式的行之前写下所有内容,在文件二中写下字符串模式之后的所有内容:

例如(文件内容)

  • 代码行 1
  • 代码行 2
  • 字符串模式
  • 代码行 3

输出应该是带有代码行 1、代码行 2 的文件 1 和带有代码行 3 的文件 2。

对写文件很熟悉,可惜不知道如何判断字符串模式前后的内容。

【问题讨论】:

  • 您能举一个使用的字符串模式和代码行的例子吗? - 它是一个 .csv 文件还是一个普通的 .txt 文件?

标签: python file split


【解决方案1】:

如果输入文件适合内存,最简单的解决方案是使用str.partition()

with open("inputfile") as f:
    contents1, sentinel, contents2 = f.read().partition("Sentinel text\n")
with open("outputfile1", "w") as f:
    f.write(contents1)
with open("outputfile2", "w") as f:
    f.write(contents2)

这假设您知道分隔两部分的行的确切文本。

【讨论】:

  • +1。如果它适合内存,这是一个非常好的、干净、可读的解决方案。
  • +1 我最喜欢的,如果在内存中给出相同的警告,则更喜欢它而不是我自己的解决方案
【解决方案2】:

这种方法类似于Lev's,但使用itertools,因为它很有趣。

 dont_break = lambda l: l.strip() != 'string_pattern'

 with open('input') as source:
     with open('out_1', 'w') as out1:
         out1.writelines(itertools.takewhile(dont_break, source))
     with open('out_2', 'w') as out2:
         out2.writelines(source)

如果需要,您可以将 dont_break 函数替换为正则表达式或其他任何内容。

【讨论】:

  • 这可能是内存无法容纳的文件的最佳解决方案。 Itertools 意味着循环是在 C 端完成的,这意味着它们会更快(考虑到内存很重要的行数很多,这可能很重要)我会注意到,如果你要像这样单独定义一个 lambda,您不妨使用def 声明。
【解决方案3】:
with open('data.txt') as inf, open('out1.txt','w') as of1, open('out2.txt','w') as of2:
    outf = of1
    for line in inf:
        if 'string pattern' in line:
            outf = of2
            continue  # prevent output of the line with "string pattern" 
        outf.write(line)

将适用于大文件,因为它逐行工作。假设string pattern 在输入文件中只出现一次。我最喜欢str.partition() 方法如果整个文件可以放入内存(这可能不是问题)

使用with 可确保在您完成或遇到异常时自动关闭文件。

【讨论】:

  • 关闭,但我相信您的代码将导致“字符串模式”出现在outf2 中,当问题表明“字符串模式”应该从输出中消失时。在这种情况下,只需在outf = outf2 之后添加continue 作为下一行,它应该可以工作。
  • @Robru 我提到了使用continue 使string pattern 消失,但我想我应该更仔细地阅读这个问题:-) .. 我会更新我的解决方案,谢谢.
【解决方案4】:

一个更有效的答案,它将处理大文件并消耗有限的内存量..

inp = open('inputfile')
out = open('outfile1', 'w')
for line in inp:
  if line == "Sentinel text\n":
    out.close()
    out = open('outfile2', 'w')
  else:
    out.write(line)
out.close()
inp.close()

【讨论】:

  • 使用with 语句打开文件。
【解决方案5】:

一个简单的例子(不像 Sven 那样将文件加载到内存中):

with open('file', 'r') as r:
    with open('file1', 'w') as f:
        for line in r:
            if line == 'string pattern\n':
                break
            f.write(line)
    with open('file2', 'w') as f:
        for line in r:
            f.write(line)

这假定'string pattern' 在输入文件中出现一次。

如果模式不是固定字符串,您可以使用re 模块。

【讨论】:

  • 使用with 语句打开文件。
  • @Lattyware 这是一个 naive 示例 :) 此外,在这种特殊情况下,使用 with 调整代码比平常更复杂。
  • 然后呢? with 是最佳实践。没有理由不使用它。很难改变的想法是不正确的 - 更容易使用并确保文件关闭,即使出现异常 - 你的代码目前甚至没有尝试。
  • 你好像被冒犯了,如果你知道这是最好的主意,那为什么不使用它呢?如果您不想在没有看到代码的情况下提供代码,请向提问者索取代码,不要给出有效但隐藏潜在错误的答案 - 这对每个人都有害(例如可能遇到此问题的人正在寻找稍后回答)。我提出了一个改进答案的建议,这符合 SO 的工作方式。这不是对你的攻击,而是试图改善资源。
  • 评论显示不够清晰。本着 SO 的精神,我自己进行了编辑(并修复了另一个微妙的错误 - 模式需要换行才能工作)。
【解决方案6】:

不超过三行:

with open('infile') as fp, open('of1','w') as of1, open('of2','w') as of2:
    of1.writelines(iter(fp.readline, sentinel))
    of2.writelines(fp)

【讨论】:

  • 好点!我总是忘记iter 的那种形式。当然,它只适用于确切的已知哨兵,不适用于正则表达式匹配或类似的东西。
【解决方案7】:

你需要这样的东西:

def test_pattern(x):
    if x.startswith('abc'): # replace this with some exact test
        return True
    return False

found = False
out = open('outfile1', 'w')
for line in open('inputfile'):
    if not found and test_pattern(line):
        found = True
        out.close()
        out = open('outfile2', 'w')
    out.write(line)
out.close()

用一个适用于您的模式的测试替换该行(如果需要,使用来自 re 的模式匹配,但任何找到分隔线的东西都可以)。

【讨论】:

  • 在打开文件的地方使用with 语句。
  • @Sven:感谢您注意到错别字。恕我直言,如果您还不确切知道如何测试,那么单线器是不合适的,这只是一个易于扩展的示例,并且失败为 False。如果测试与其他 if 语句成为多行,例如查找前 2 个字符,然后在 '|' 上拆分并检查以下两个字符,那么这更容易适应。
  • @Lattyware:with 很好但不合适,因为它是 Python 的一个相对较新的补充,我们不知道 dom_frank 使用的是哪个版本的 Python。
  • @Anthon 刚刚学习 python 的人不会使用 2.5 之前的任何东西;如果 OP 使用的是 2.5,那么他只需要添加from __future__ import with_statement
  • @Anthon 仅仅因为某些东西是新的并不意味着它应该被避免,除此之外,正如 Dougal 所说,这绝不是一个新功能。这是标准的,每个人(他们应该)都使用它。我认为任何不使用它的新代码都是错误的——它会无缘无故地引入潜在的错误并降低可读性。
猜你喜欢
  • 1970-01-01
  • 2019-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-25
  • 1970-01-01
相关资源
最近更新 更多