Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何执行缓冲搜索和替换?_Python_Xml_Buffer_Replace - Fatal编程技术网

Python 如何执行缓冲搜索和替换?

Python 如何执行缓冲搜索和替换?,python,xml,buffer,replace,Python,Xml,Buffer,Replace,我有一些XML文件,其中包含导致解析失败的内容。它们看起来像。为了解决这个问题,我用一个转义序列替换整个事件来转义它们:;-->#~10^。然后,在我完成解析之后,我可以将它们恢复到原来的状态 buffersize = 2**16 # 64 KB buffer def escape(filename): out = file(filename + '_esc', 'w') with open(filename, 'r') as f:

我有一些XML文件,其中包含导致解析失败的内容。它们看起来像
。为了解决这个问题,我用一个转义序列替换整个事件来转义它们:
;-->#~10^
。然后,在我完成解析之后,我可以将它们恢复到原来的状态

buffersize = 2**16   # 64 KB buffer

def escape(filename):
    out = file(filename + '_esc', 'w') 

    with open(filename, 'r') as f:
        buffer = 'x'     # is there a prettier way to handle the first one?
        while buffer != '':
            buffer = f.read(buffersize)
            out.write(re.sub(r'&#x([a-fA-F0-9]+);', r'!#~\1^', buffer))

    out.close()
文件非常大,所以我必须使用缓冲(给了我一个
内存错误
)。因为缓冲区的大小是固定的,所以当缓冲区恰好小到足以拆分序列时,我会遇到问题。假设缓冲区大小为8,文件如下所示:

 123456789
 hello!&x10;

缓冲区将只读取
hello&x
,允许
和x10以从裂缝中滑出。我如何解决这个问题?如果最后几个字符看起来可能属于一个字符序列,我想得到更多的字符,但我想到的逻辑非常糟糕。

如果序列长度为6个字符,则可以使用具有5个重叠字符的缓冲区。这样,您就可以确定缓冲区之间不会有序列滑动

以下是一个帮助您可视化的示例:

--&#x10
  --

--
   #x10;--
至于实现,只需将最后一个缓冲区的最后5个字符前置到新缓冲区:

buffer = buffer[-5:] + f.read(buffersize)
唯一的问题是连接可能需要整个缓冲区的副本。另一种解决方案是,如果您可以随机访问该文件,请使用以下方法稍微倒带一点:

f.seek(-5, os.SEEK_CUR)

在这两种情况下,您都必须稍微修改脚本以处理第一次迭代。

首先,不要费心读写文件,您可以创建一个类似文件的对象来包装打开的文件,并在解析器处理数据之前对其进行处理。第二,您的缓冲可以只处理读取字节的结尾。下面是一些工作代码:

class Wrapped(object):
    def __init__(self, f):
        self.f = f
        self.buffer = ""

    def read(self, size=0):
        buf = self.buffer + self.f.read(size)
        buf = buf.replace("!", "!!")
        buf = re.sub(r"&(#x[0-9a-fA-F]+;)", r"!\1", buf)
        # If there's an ampersand near the end, hold onto that piece until we
        # have more, to be sure we don't miss one.
        last_amp = buf.rfind("&", -10, -1)
        if last_amp > 0:
            self.buffer = buf[last_amp:]
            buf = buf[:last_amp]
        else:
            self.buffer = ""
        return buf
然后在代码中替换以下内容:

it = ET.iterparse(file(xml, "rb"))
为此:

it = ET.iterparse(Wrapped(file(xml, "rb")))

第三,我使用了一个替换,将“&”替换为“!”,将“!”替换为“!!”,这样您可以在解析后修复它们,而不必依赖模糊序列。这毕竟是堆栈溢出数据,因此许多奇怪的随机标点符号可能会自然出现。

包装器是个好主意。。。但是如果您将“!”替换为“!!”,那么您原来的“!!”将替换为“!”。我不认为有什么好办法。将“!”替换为“!!”意味着在最终输出中,每个“!”都是转义字符,您可以查看下一个字符来决定要做什么:“!”下一个表示只输出一个“!”,“#”下一个表示输出一个数字实体。这与格式字符串中的“%”和“%”相同。