首页 > 解决方案 > 如何使用python从大文件中删除特定行?

问题描述

为了工作,我必须处理一个基于 XML 的文件:将它放在另一个目录中,更改扩展名(从 .xaf 到 .xml),从行中读取一些信息并从文件中删除两个特定行(在它被替换之后。
我除了最后一部分之外,一切正常。我需要删除两个特定的行(或者如果 xml 的内容写在一行中,则从一行中删除两个特定部分)。这应该不是问题,已经有很多关于在stackoverflow上,经常给出的解决方案是从源文件中读取,逐行复制(需要删除的行除外)整个文件
,问题是我需要处理的文件非常多大(从 100.000 到 >5.000.000 行),并且有很多文件要处理,因此执行此方法需要很长时间。
有没有办法复制文件并直接编辑内容,而不是逐行复制文件?需要删除的部分总是在前 20 行中。

我尝试将文件从源复制到目标,然后再次打开源文件以读取前 20 行并将它们复制到目标文件。然而,这意味着整个目标文件都被覆盖了(所以这 20 行之后的所有内容都消失了)。

有谁知道如何处理这个问题?非常感谢

示例部分:\

   \<companyIdent>XXXXX\</companyIdent>\
\<companyName>Company1\</companyName>\
\<taxRegistrationCountry>NL\</taxRegistrationCountry>\
\<taxRegIdent>123456789\</taxRegIdent>\
\<streetAddress>
    \<streetname>Address1\</streetname>\
    \<city>CITY\</city>\
    \<postalCode>1234AB\</postalCode>\
    \<country>NL\</country>\</streetAddress>\
\<customersSuppliers>
   \<customerSupplier>
      \<custSupID>C0001\</custSupID>\

我想删除<streetAddress> 和</streetAddress>。只有这两个标签,而不是其中的内容(这就是为什么我想删除行而不是解析它)

标签: pythonxmlfile

解决方案


使用基于事件的 SAX 解析器,您可以过滤内存使用率低且性能良好的标签:

from xml.sax import make_parser
from xml.sax.saxutils import XMLFilterBase, XMLGenerator

# filter class which skips startElement and endElement events
# for tags configured
class MyFilter(XMLFilterBase):

    def __init__(self, tags_to_exclude, parent=None):
        super().__init__(parent)

        # tags to exclude
        self._tags_to_exclude = tags_to_exclude

    def startElement(self, name, attrs):
        if name not in self._tags_to_exclude:
            super().startElement(name, attrs)

    def endElement(self, name):
        if name not in self._tags_to_exclude:
            super().endElement(name)


# define tags to be ecluded    
tags_to_exclude = {'streetAddress'}

# create filter    
reader = MyFilter(tags_to_exclude, make_parser())

# parse source and write to target
with open('target.xml', 'w') as file:
    handler = XMLGenerator(file)
    reader.setContentHandler(handler)
    reader.parse('source.xml')

推荐阅读