我需要将二进制数据嵌入到 XML 文件中,因此我选择使用 base85 编码。
我有一个大型字节数组,其中填充了通过 bytearray.extend(struct.pack(variing_data))
调用 struct.pack()
的输出。然后使用 zlib
进行压缩并使用 base64.b85encode()
进行编码。
这一直有效,但是在单个输入文件上,出现以下奇怪的错误:
ValueError: base85 overflow in hunk starting at byte 582200`
然后我修改了 base64.py 以打印出当前 block 具有哪个值以及它由哪些字节组成。输入 block 为 b'||a|3'
,其值为 4.331.076.573,大于 256^4 = 4.294.967.296 strong> 因此不能用四个字节表示(这就是错误的来源)。
但我不明白的是:怎么会发生这种事?
这是代码的重要部分:
elif isinstance(self.content, (bytes, bytearray)):
base85 = zlib.compress(self.content, 9)
# pad=False doesn't make a difference here
base85 = base64.b85encode(base85, pad=True).decode()
base85 = escape_xml(base85)
file.write(base85)
def escape_xml(text):
text = text.replace("&", "&")
text = text.replace("<", "<")
text = text.replace(">", ">")
text = text.replace("\"", """)
text = text.replace("'", "'")
return text
以及解码代码:
def decode_binary_data(data):
data = unescape_xml(data)
# Remove newline for mixed content support (does not apply in this case)
data = data.split("\n", 1)[0]
# Error!
data = base64.b85decode(data)
return zlib.decompress(data)
def unescape_xml(text):
text = text.replace(""", "\"")
text = text.replace("'", "'")
text = text.replace("<", "<")
text = text.replace(">", ">")
text = text.replace("&", "&")
return text
Base85 理论上可以与 85^5 = 4.437.053.125 可能的组合一起使用,但当它从字节获取输入时,我想知道这是如何可能的。这是来自压缩吗?这不应该是问题,因为编码和解码应该是对称的。如果是问题,如何压缩数据?
选择 Ascii85 (a84encode()
) 可以,但我认为这并不能真正解决问题,也许在其他情况下会失败?
感谢您的帮助!
最佳答案
我发现问题了! Base85 算法和压缩都不是这里的问题。它是 XML。
为了使用包含的 base85 字符串导出/写入 XML,我编写了自己的类和函数来导出 XML,以便它看起来很漂亮(xml.etree.ElementTree
将所有内容写入一行并为这个项目我不能使用 pip 中的外部包)。这就是为什么必须手动转义 base85 字符串。
但是为了读取 XML 文件,我使用 xml.etree.ElementTree
。 我不知道大多数 XML 库都会自动转义字符串(这是有道理的)。
所以,问题在于手动取消转义,ElementTree
自动执行。结果,base85 字符串两次未转义。由于 base85 字母表包含 XML 转义字符串中包含的每个字母($amp;
、$lt;
等),并且该 base85 字符串中包含超过 500.000 个字符,输出字符串中很可能存在形成有效 XML 转义字符串的字符组合。
这就是问题所在。 <
包含在未转义的 base85 字符串中,并再次未转义,导致所有后续字节的偏移,从而导致此错误。
关于python - Base85编码字符串解码时出现base85溢出错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56530892/