AS3 CookBook学习整理(十五)
1. 通过URLLoader读取文本数据
URLLoader可以读取三种格式的数据,分别为URLLoaderDataFormat的枚举值:BINARY(二进制)、TEXT(普通文本)、VARIABLES(URL编码)
URLLoader.data 属性的数据类型是根据dataFormat 属性的设置而决定的,如果设置为DataFormat.TEXT,则data 属性的值为String 类型,如果设置DataFormat.VARIABLES,则是Object 类型,如果设置为DataFormat.BINARY,则data 的数据类型为flash.util.ByteArray
当设置loader.dataFormat = URLLoaderDataFormat.VARIABLES时,源数据必须为符合规范的URL编码数据,需要遵循下面几个规则:
* 以 name=hxw&age=27 这样的形式出现
* 空格被替换成"+"符号,不是%20,例如:name=bill+gates (空格和%20也可以用,但是用"+"兼容性更好)
* 其它都与.net的URL编码一致
URLLoader读取数据时,会触发一系列的事件:
Event.OPEN -- 开始从服务器下载数据时加载一次,此时的URLLoader.bytesLoaded一定是0
Event.COMPLETE -- 数据完全加载完毕时触发, 通常如果能够触发这个事件的话, 说明你的程序没有问题
ProgressEvent.PROGRESS -- 在从服务器下载数据的过程中持续触发, 通过侦听它的变化我们可以很方便的为 URLLoader 做加载状态的显示
IOErrorEvent.IO_ERROR -- 当遇到致命错误导致下载终止
SecurityErrorEvent.SECURITY_ERROR -- FlashPlayer 的安全错误,试图读取安全沙漏允许以外的域数据(跨域加载)
HTTPStatusEvent.HTTP_STATUS -- 获取 HTTP 状态代码时触发, 通过判断它的status属性我们可以获得远程文件的加载状态,成功 (200)、没有权限 (403)、找不到文件 (404)、服务器内部错误 (500) 等等。这个事件总是在 compelete 之前被触发
package { import flash.display.Sprite; import flash.events.Event; import flash.events.HTTPStatusEvent; import flash.events.IOErrorEvent; import flash.events.ProgressEvent; import flash.events.SecurityErrorEvent; import flash.net.URLLoader; import flash.net.URLLoaderDataFormat; import flash.net.URLRequest; public class Sample0707 extends Sprite { public function Sample0707() { var loader:URLLoader = new URLLoader(new URLRequest("file.txt")); loader.dataFormat = URLLoaderDataFormat.VARIABLES; loader.addEventListener(Event.OPEN,onOpen); loader.addEventListener(HTTPStatusEvent.HTTP_STATUS,onHttpStatus); loader.addEventListener(IOErrorEvent.IO_ERROR,onIOError); loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR,onSecurityError); loader.addEventListener(ProgressEvent.PROGRESS,onProgress); loader.addEventListener(Event.COMPLETE,onComplete); } private function onOpen(event:Event):void { trace("开始下载"); } private function onComplete(event:Event):void { trace("Load Complete"); var loader:URLLoader = event.target as URLLoader; for(var str:String in loader.data) { trace(str + ":" + loader.data[str]); } } private function onProgress(event:ProgressEvent):void { trace("Loading……"); } private function onHttpStatus(event:HTTPStatusEvent):void { trace("http请求状态代码:" + event.status); } private function onIOError(event:IOErrorEvent):void { trace("致命错误导致下载终止"); } private function onSecurityError(event:SecurityErrorEvent):void { trace("试图读取安全沙漏允许以外的域数据"); } } }
2. 解决URLLoader读取数据的乱码问题
flash.system.System.useCodePage = true;
useCodePage -- Flash Player使用哪个代码页来解释外部文件,默认为false。为flase时,Flash Player使用Unicode解释外部文本文件。(保存这些文件时,必须使用Unicode对其进行编码);当该属性设置为true时,Flash Player使用运行播放器的操作系统的传统代码页来解释外部文本文件
如果将userCodePage设置为true,应注意:在运行播放器的操作系统的传统代码页中必须包括您的外部文本文件中使用的字符,这样才能显示文本。为确保所有平台上的用户都能查看您的swf文件中使用的外部文本文件,应将所有外部文本文件按Unicode进行编码,并保留useCodePage为false
3. 边下载边访问数据(URLStream)
使用flash.net.URLStream可以在下载的过程中立即读取二进制数据
URLLoader必须等数据全部下载完才能读取数据,当URLLoader的dataFormat属性为URLLoaderDataFormat.BINARY时和URLStream非常类似,它们有相同的事件,关键的区别是处理progress事件的方式不同而已
在URLStream中的progress事件允许使用bytesAvailable属性来得到可用的数据,然后调用readInt()、readByte()和readBoolean()等方法来读取数据
当访问的数据都是二进制时最好使用URLStream
PS: 在进行读取数据时,需要检测一下bytesAvailable的值,如果读取的字节超出缓冲的结果则会抛出EOFError异常
package { import flash.display.*; import flash.events.ProgressEvent; import flash.net.URLLoaderDataFormat; import flash.net.URLRequest; import flash.net.URLStream; public class Sample0707 extends Sprite { public function Sample0707() { var loader:URLStream = new URLStream(); loader.load(new URLRequest("http://www.hardfest.com/hhm09.html")); loader.addEventListener(ProgressEvent.PROGRESS,onProgress); } private function onProgress(event:ProgressEvent):void { var loader:URLStream = event.target as URLStream; while ( loader.bytesAvailable > 0 ) { trace("Read byte: " + String.fromCharCode(loader.readByte())); } } } }
4. 发送数据给服务端页面
调用sendToURL(urlRequest)或navigateToURL(urlRequest, windowLocation)
这两种方法都无法返回结果,如果要返回结果可以使用URLLoader
可以利用sendToURL(urlRequest)来做插入数据库的操作
package { import flash.display.Sprite; import flash.net.URLRequest; import flash.net.URLRequestMethod; import flash.net.URLVariables; import flash.net.sendToURL; public class Sample0708 extends Sprite { public function Sample0708() { var variables:URLVariables = new URLVariables(); variables.userName = "信春哥考本科"; var request:URLRequest = new URLRequest(); request.url = "http://localhost:4671/Default.aspx"; request.data = variables; request.method = URLRequestMethod.POST; sendToURL(request); } } }
可以利用navigateToURL(urlRequest, windowLocation)来做查询
package { import flash.display.Sprite; import flash.net.URLRequest; import flash.net.URLRequestMethod; import flash.net.URLVariables; import flash.net.navigateToURL; import flash.system.System; public class Sample0708 extends Sprite { public function Sample0708() { flash.system.System.useCodePage = true; var variables:URLVariables = new URLVariables(); variables.wd = "春哥纯爷们"; var request:URLRequest = new URLRequest(); request.url = "http://www.baidu.com/s"; request.data = variables; request.method = URLRequestMethod.POST; navigateToURL(request,"_target"); } } }
PS:如果是以URLRequestMethod.GET的形式传递数据,则后台需要用Request.QueryString["keyword"]来获取;如果是以URLRequestMethod.POST的形式传递,则后台需要用Request.Form["keyword"]来获取
5. 发送数据并返回结果
使用URLLoader来实现
服务器端代码(.net)
protected override void Render(HtmlTextWriter writer) { //base.Render(writer); string id = Request.Form["userID"]; SqlConnection conn = new SqlConnection("server=127.0.0.1;database=test;uid=sa;pwd="); conn.Open(); SqlCommand cmd = new SqlCommand("select userName from t_User where userID=" + id, conn); string resultValue = cmd.ExecuteScalar().ToString(); conn.Close(); Response.Write("name=" + resultValue); }
flex代码:
package { import flash.display.Sprite; import flash.events.Event; import flash.net.URLLoader; import flash.net.URLLoaderDataFormat; import flash.net.URLRequest; import flash.net.URLRequestMethod; import flash.net.URLVariables; public class Sample0708 extends Sprite { public function Sample0708() { var infoObj:URLVariables = new URLVariables(); infoObj.userID = 3; var request:URLRequest = new URLRequest(); request.url = "http://localhost:4671/Detail.aspx"; request.method = URLRequestMethod.POST; request.data = infoObj; var loader:URLLoader = new URLLoader(); loader.dataFormat = URLLoaderDataFormat.VARIABLES; loader.load(request); loader.addEventListener(Event.COMPLETE,onComplete); } private function onComplete(event:Event):void { var loader:URLLoader = event.target as URLLoader; trace(loader.data.name); } } }
6. 创建XML对象
方法一:创建XML对象并直接用XML进行赋值
var str:String = "栏目A"; var xml:XML = <menu><item>{str}</item><item>栏目B</item></menu>;
方法二:传递XML字符串给XML构造函数
var str:String = "<menu><item>栏目A</item><item>栏目B</item></menu>"; var xml:XML = new XML(str);
7. 为XML添加节点
可以直接用E4X语法添加新节点,有两种方式:xml.newNode = "content" 和 xml["newNode"] = "content",区别在于假如出现xml.my-item这样的节点会编译出错,只能用xml["my-item"]
var xml:XML = <menu />; xml.item1 = "栏目A"; xml.item2 = "栏目B"; xml["item3"] = "栏目C"; //xml.my-item = "栏目D"; 错误 xml["my-item"] = "栏目D";
还可以使用XML对象的insertChildBefore()和insertChildAfter()方法来动态插入节点
insertChildBefore(child1, child2) -- 在child1节点之前插入child2节点,如果child1为null,则在所有子项之后插入child2节点(理解为"不在任何节点之前,即在最后")
insertChildAfter(child1, child2) -- 在child1节点之后插入child2节点,如果child1为null,则在所有子项之前插入child2节点(理解为"不在任何节点之后,即在最前")
prependChild(child) -- 在xml最前面插入新节点
appendChild(child) -- 在xml最后面插入新节点
package { import flash.display.Sprite; public class Sample0708 extends Sprite { public function Sample0708() { var xml:XML = <menu> <item>栏目A</item> <item>栏目B</item> <distinctItem>特别栏目</distinctItem> <item>栏目C</item> </menu>; //在所有节点之后插入新节点 xml.insertChildBefore(null,<itemAAA />); //在所有节点啊之前插入新节点 xml.insertChildAfter(null,<itemBBB>栏目BBB</itemBBB>); //在某一节点之前插入新节点 xml.insertChildBefore(xml.item[1],<itemCCC />); //在某一节点之后插入新节点 xml.insertChildAfter(xml.distinctItem,<itemDDD />); //在xml最前面插入新节点 xml.prependChild(<firstItem />); //在xml最后面插入新节点 xml.appendChild(<lastItem />); trace(xml); } } }
8. 为XML元素添加属性
使用E4X的@操作符
需要注意的是,如果出现"s-title"、"click"+num这样形式的属性名,使用node.@attribute会编译错误,需要使用node.@["attribute"]的方式
package { import flash.display.Sprite; public class Sample0708 extends Sprite { public function Sample0708() { var xml:XML = <menu> <item>栏目A</item> <item>栏目B</item> <distinctItem>特别栏目</distinctItem> <item>栏目C</item> </menu>; xml.item[1].@title = "魔兽世界"; xml.distintItem.@["s-title"] = "永恒之塔"; var num:int = 101; xml.item[0].@["click"+num] = 0; trace(xml); } } }
9. 读取XML树中的元素
使用xml.elements()方法范围XMLList类型的所有元素,并用for each循环遍历,注意调用一次elements只能返回下一级的子元素节点,要访问整个XML结构,需要进行递归处理
package { import flash.display.Sprite; public class Sample0708 extends Sprite { public function Sample0708() { var xml:XML = <menu> <item>栏目A</item> <item title="一个标题">栏目B</item> <distinctItem><subItem>特别栏目</subItem></distinctItem> <item>栏目C</item> </menu>; getNode(xml); } private function getNode(node:XML):void { var nodeList:XMLList = node.elements(); for each(var subNode:XML in nodeList) { trace(subNode.toXMLString()); trace(subNode.@title); } } } }
10. 查找XML元素节点
使用E4X的操作符(.)加上属性名语法来查找元素,也可以使用操作符(..)来访问第二级的节点(跳过一级)
如果有多个同名的节点,可以使用item[index]来访问
需要注意的是:[]操作符不能和双点操作符一起使用,例如fruit..[nodeName];是错误的
package { import flash.display.Sprite; public class Sample0709 extends Sprite { public function Sample0709() { var xml:XML = <menu> <item>栏目A</item> <item>栏目B</item> <distinctItem title="一个标题">
<subItem>
<park>特别栏目</park>
</subItem>
</distinctItem> <item>栏目C</item> </menu>; trace(xml.item[1]); trace(xml..subItem.park); } } }