使用字节数组解压Zlib字符串
我有一个用Adobe Flex 3和Python 2.5开发的网页应用程序,部署在Google App Engine上。现在我在Python中创建了一个RESTful网络服务,返回的结果是XML格式,Flex通过HttpService对象来读取这些结果。
我的主要目标是压缩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
1 个回答
byteArray.writeUTF( event.result.toString() );
这个代码是干什么的呢?zlib.compress() 的结果既不是 Unicode 也不是“UTF”(后面没有数字就没意义!?);它是二进制数据,也就是原始字节;你不应该对它进行解码、编码或任何其他转换。接收方应该立即解压收到的原始字节,以恢复传递给 zlib.compress() 的数据。
更新 你有什么文档支持 byteArray.uncompress()
期待的是一个真正的 zlib 流,而不是 deflate 流(也就是说,zlib 流在你剪掉前两个字节和最后四个字节之后)?
Flex 3 的 ByteArray 文档给了这个例子:
bytes.uncompress(CompressionAlgorithm.DEFLATE);
但并没有说明默认值是什么(如果有的话)。如果有默认值,文档里并没有明显的地方提到,所以你最好使用
bytes.uncompress(CompressionAlgorithm.ZLIB);
这样可以明确你的意图。
而且文档提到了 writeUTFBytes
方法,而不是 writeUTF
方法。你确定你在问题中复制粘贴的接收代码是完全正确的吗?
更新 2
谢谢你提供的链接。看起来我拿到的是“帮助”,而不是正式文档 :=(. 有几点需要说明:
(1) 是的,确实有一个明确的 inflate()
方法。不过,uncompress 确实有一个算法参数;它可以是 CompressionAlgorithm.ZLIB(默认)或者 CompressionAlgorithm.DEFLATE……有趣的是,后者仅在 Adobe Air 中可用,而在 Flash Player 中不可用。至少我们知道 uncompress() 调用看起来没问题,我们可以回到如何将原始字节传输到网络并再转回 ByteArray 实例的问题上。
(2) 更重要的是,有 writeUTF
(将 UTF-8 字符串写入字节流。首先写入 UTF-8 字符串的字节长度,作为 16 位整数,然后是表示字符串字符的字节)和 writeUTFBytes
(将 UTF-8 字符串写入字节流。与 writeUTF() 方法类似,但 writeUTFBytes() 不会在字符串前加上 16 位长度字)。
无论提供 UTF8 编码字节有什么好处(在我看来没有),你都不想在这里加上 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 中获取原始字节。
希望这些对你有帮助,
约翰