Chen Sheng

岂曰无错 与子偕论 岂曰无正 与子偕证

« 病毒清除后,服务无法启动怎么办?sqlplus 使用摘录 »

ByteArray 使用摘录 utf-16与ByteArray的恩怨 flex中文乱码之谜

ByteArray是一种有用的对象
他有3个值得注意的属性
position 及 length,endian

ByteArray 有二种操作
一种是Read系列,主要是将从position开始的,返回某种类型长度或指定长度的缓冲,返回结果会做根据字节顺序一些处理,同时postion会自动移到读取缓冲的终点。

二是Write系列,也是从position开始,写入某种类型长度或指定长度的数据(必要时会根据字节顺序作处理),同时position会自增。

要注意的有几点
1)字节顺序
 var b:ByteArray= new ByteArray;
 b.endian=flash.utils.Endian.BIG_ENDIAN;
 b.writeShort(0x1234);
 b.position=0;
 trace(b.readByte());//=0x12,如果b.endian=flash.utils.LITTLE_ENDIAN,则是0x34
2)readBytes
ByteArray.readBytes(bytes:ByteArray, offset:uint = 0, length:uint = 0):void
Reads the number of data bytes, specified by the length parameter, from the byte stream.



var b:ByteArray= new ByteArray;
var a:ByteArray= new ByteArray;
..
b.ReadBytes(a,o,l);

这时从b的角度来考虑,b是从b.position开始读取b的内容的。
从a的角度来看,a被写的数据是存放在[o,o+l)这段空间的,这时不关心a的position在何处。
如果a的长度原来不够,则会自动增长到o+l长度。

3)writeBytes
public function writeBytes(bytes:ByteArray, offset:uint = 0, length:uint = 0):void
var b:ByteArray= new ByteArray;
var a:ByteArray= new ByteArray;
...
b.writeBytes(a,o,l);
表示从b.postion 开始写入从a的o处开始l 长度的缓冲到b


4) 关于字符集的问题
ByteArray在处理utf-8及普通字符集都没有太大问题(通过read/writeUTF/MultiByte)
但在处理utf-16时有点小麻烦。
也就说,如果ByteArray存放的是utf-16则有些问题。

flex 自己的文档 “Supported Character Sets”  有这么一行:Unicode (Big-Endian) unicodeFFFE ,也就是说 0xFFFE flex当成大端的BOM,然而恰恰相反,这似乎应该是小端BOM吧。
所以当byteArray存放的是ucs-2时,即无论是大端还是小端,或者你怎么设置都不能正确得到字符串。晕啊。
这太郁闷了,当有BOM存在时,经过代码验证,flex是忽略ByteArray的endian设置的---只要有BOM存在(这是有道理的,因为bom决定了字节顺序)。

我写了一个小小的flex页面(页面及代码见文章最后),专门来测试,试了大把的charset 。最后的结果是让我对使用readMultiByte读取ucs-2(utf16-be or utf16-le)的缓冲不抱任何希望。

因此凡是utf-16编码的ByteArray得通过另外的方法来取得--而且有比较简单的方法(运气啊!是运气,还是因为上帝在这里关上门,就会在另一面打开一扇窗?)

ByteArray中缓冲区的数据要符合二个条件就可以读出

  1. 必须得有BOM
  2. BOM之后的数据流字节顺序与BOM是一致的

 

这样就可以通过ByteArray.toString()得到 String了!

小小代码例子:

var s:String = "123中国";
var b:ByteArray= new ByteArray;
b.writeByte(0xFF);
b.writeByte(0xFE);
b.endian=Endian.LITTLE_ENDIAN; //与上面的BOM对应起来
for ( var i:int = 0 ; i <s.length ; ++i )
{
 buff.writeShort( s.charCodeAt( i ));
}

var news:String = b.toString();
trace(news);

// or

var s:String = "123中国";
var b:ByteArray= new ByteArray;
b.writeByte(0xFE);
b.writeByte(0xFF);
b.endian=Endian.BIG_ENDIAN; //与上面的BOM对应起来
for ( var i:int = 0 ; i <s.length ; ++i )
{
 buff.writeShort( s.charCodeAt( i ));
}

var news:String = b.toString();
trace(news);

 

我测试的flash程序所在

http://chensheng.net/p/test-bytearray/

源代码点右键可以看到,utf-16字符串与byteArray之间的相互转换

 

 btw:这好象是一个bug

请参见:http://bugs.adobe.com/jira/browse/FP-716

呵呵,这么说来,许多中文论坛上关于 Flex 中文乱码 的麻烦是有原因的,我这才是解决之首。

 

  • 相关文章:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

日历

最新评论及回复

最近发表

Powered By Z-Blog 1.8 Arwen Build 81206

Copyright 2000-2008 @ chensheng.net.(qq:99479) All Rights Reserved.
浙ICP备09092413号