使用ByteArray解压Zlib字符串

5
我有一个采用Adobe Flex 3和Python 2.5开发的Web应用(部署在Google App Engine上)。使用Python创建了一个RESTful Web服务,其结果目前以XML格式呈现,并通过HttpService对象被Flex读取。
现在的主要目标是压缩XML,以使得HttpService的send()方法和结果事件之间的时间尽可能短。我查阅了Python文档并成功使用zlib.compress()来压缩XML结果。
然后,我将HttpService的结果类型从“xml”设置为“text”,并尝试使用ByteArrays将字符串解压缩回XML。这里我失败了。我的操作类似于这样:
var byteArray:ByteArray = new ByteArray();
byteArray.writeUTF( event.result.toString() );
byteArray.uncompress();
var xmlResult:XML = byteArray.readUTF();

在byteArray.uncompress()处抛出异常,提示无法解压缩byteArray。当我跟踪byteArray的长度时,它变成了0。

无法弄清楚我做错了什么。欢迎所有帮助。

-- 编辑 --

代码:

# compressing the xml result in Python
print zlib.compress(xmlResult)

# decompresisng it in AS3
var byteArray:ByteArray = new ByteArray();
byteArray.writeUTF( event.result.toString() );
byteArray.uncompress()

事件类型为ResultEvent。

错误信息:

错误:错误#2058:解压数据时出错。

可能的原因是byteArray.bytesAvailable的值为0,这意味着python生成的原始字节没有正确地写入byteArray中。

-- Sri


请编辑您的问题以显示精确的错误消息。 - John Machin
在Python端:您如何将压缩数据放入线路中? - codeape
@codeape,zlib.compress() 返回一个字符串,然后将其“print”以供 Flex HttpService 对象读取。这样正确吗? - Sri
1个回答

2
byteArray.writeUTF(event.result.toString());的作用是什么?zlib.compress()的结果既不是Unicode,也不是“UTF”(没有数字无意义!);它是二进制的,也就是原始字节;你不应该对其进行解码、编码或应用任何其他转换。接收者应立即对接收到的原始字节进行解压缩,以恢复传递给zlib.compress()的数据。
更新:您有哪些文档支持byteArray.uncompress()期望的是真正的zlib流,而不是deflate流(即在您剪下前2个字节和最后4个字节之后的zlib流)?
Flex 3 ByteArray文档提供了以下示例: bytes.uncompress(CompressionAlgorithm.DEFLATE); 但未说明默认值(如果有的话)。如果有默认值,则没有明显的地方记录,因此最好使用 bytes.uncompress(CompressionAlgorithm.ZLIB); 以清楚显示您的意图。
文档中有一个writeUTFBytes方法,而不是writeUTF方法。您确定在问题中复制/粘贴了确切的接收器代码吗?
更新2:
感谢URL。看起来我拿到了“帮助”,而不是真正的文档:=(。
一些要点:
(1)是的,有一个显式的inflate()方法。但是,uncompress确实具有算法参数;它可以是CompressionAlgorithm.ZLIB(默认值)或CompressionAlgorithm.DEFLATE...有趣的是,后者只在Adobe Air中可用,而不在Flash Player中。至少我们知道uncompress()调用看起来没问题,我们可以回到把原始字节放到电线上并再次转换为ByteArray实例的问题上。
(2)更重要的是,writeUTF(将UTF-8字符串写入字节流。首先以16位整数形式写入UTF-8字符串的长度,然后是表示字符串字符的字节)和writeUTFBytes(将UTF-8字符串写入字节流。类似于writeUTF()方法,但writeUTFBytes()没有使用16位长度字作为前缀的字符串)都存在。
无论提供UTF8编码的字节(无用,IMHO)如何,您都不想在那里使用2字节的长度前缀;使用writeUTF()会导致uncompress()失败。
将其发送到网络上:在二进制数据上使用Python print似乎不是一个好主意(除非sys.stdout已被禁用以在原始模式下运行,但您的代码中没有显示)。同样,使用event.result.toString()获取一个字符串(类似于Python unicode对象,是/否?)-然后对其进行UTF-8编码似乎不太可能起作用。鉴于我直到今天才知道flex的存在,我真的无法有效地帮助您。以下是一些进一步建议,以便自己独立解决问题,以防没有更多了解flex的人很快就会出现:(1)进行一些调试。从最小的XML文档开始。显示repr(xml_doc)。显示repr(zlib_compress_output)。在(裁剪版本的)flex脚本中,使用尽可能接近repr()的函数/方法来显示:event.result,event.result.toString()和writeUTF*()的结果。确保您理解在zlib.compress()之后可能发生的所有事情的影响。认真阅读文档可能有助于解决问题。(2)查看如何从event.result中获取原始字节。希望这有所帮助,John

zlib.compress(xml)会给我一个字符串形式的原始字节吗?那么我的问题是如何将这些原始字节“喂”到ByteArray中,然后使用uncompress方法读取XML字符串。或者您是说我需要使用base64.encode()将原始字节编码为字符串?如果问题看起来很愚蠢,请原谅.. :P - Sri
“既不解码也不编码” == 我说过你需要使用“base64.encode()”吗?简单来说,接收者必须要将发送者所做的反向操作。而我们并不确定发送者所做的操作,因为你没有展示发送代码。请编辑你的问题以包括(a)精确的错误信息(b)发送者代码。event.result.toString()是什么类型?你尝试过解压缩它吗[即我认为我在说什么]? - John Machin
"更新:您拥有哪些文档支持byteArray.uncompress()期望真正的zlib流而不是(a)压缩流(即在剪去前2个字节和最后4个字节之后的zlib流)或(b)其他内容的概念?" --- ByteArray具有特定的inflate() / deflate()方法,用于处理“压缩”的流..." - Sri
请提供一个指向该URL的链接。你是不是想说我在答案中给出的URL不是Adobe Flex 3语言的ByteArray类?顺便说一句,我现在得出去了;希望有更多了解这门语言的人能够过来 :-) - John Machin
请查看:http://www.adobe.com/livedocs/flex/3/langref/flash/utils/ByteArray.html - Sri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接