AS3對象序列化存儲

AS3對象序列化存儲

23.6.1.問題
我想對自定義對象進行序列化並保存到硬盤驅動器的文件中。
23.6.2.解決辦法
通過class-alias註冊自定義類,使用ActionScript Message Format (AMF) 編碼序列化對象,並使用FileStream.writeObject方法把對象存儲到文件上。
23.6.3.討論
使用AIR文件系統API,你可以把經過AMF編碼序列化過的對象寫入文件流緩衝區中。

ActionScript語言中大多數內建對象類型比如String和Boolean都自動支持序列化。這些類型同通過AMF被編碼爲二進制格式,當經過反序列化可以恢復原來的值。然而自定義對象是不自動支持序列化的,要啓動自定義對象序列化支持,你需要用registerClassAlias 方法用一個類別名註冊此類,或者在類定義前申明這個[RemoteClass]元數據標籤。

假定你的程序要把用戶信息作爲一個對象進行顯示,可過一段時間被同一個程序或者被其他程序載入,這些程序應已知道如何處理該對象,要表現用戶信息的自定義對象看起來大概是下面這樣:

+展開
-ActionScript
package com.oreilly.flexcookbook {
[RemoteClass]
[Bindable]
public class UserData {
public var firstName:String;
public var lastName:String;
public var age:Number;
public var sessionLength:Number;
public function UserData( firstName:String = "",lastName:String = ""){
this.firstName = firstName;
this.lastName = lastName;
}
}
}


每次你的程序被用戶打開時,一個新的UserData對象被創建,等待用戶輸入信息,通常可以保存這些信息以特定的格式保存到文本文件上,但是你也可以序列化對象到文件上,從而可輕易的以對象類型讀取,不必要解析字符串,重置UserData新實例屬性。要序列化對象且通過反序列化保留其屬性值,需要使用[RemoteClass]元數據標籤註冊它。

在類申明前插入[RemoteClass] 元數據標籤,可啓動此類在使用AMF序列化和反序列化中能保持類型信息和屬性值。你也可以在變量定義前加上[Transient]元數據標籤,指示此變量不會被序列化。比如上面例子中的sessionLength屬性每次程序運行時都會更新,因爲沒必要進行保存,你可以把此屬性標記爲transient屬性拒絕被序列化:

+展開
-ActionScript
package com.oreilly.flexcookbook {
[RemoteClass]
public class UserData {
public var firstName:String;
public var lastName:String;
public var age:Number;
[Transient]
public var sessionLength:Number;
public function UserData( firstName:String = "",lastName:String = ""){
this.firstName = firstName;
this.lastName = lastName;
}
}
}


使用FileStream.writeObject方法把序列化自定義對象寫到文件裏,當使用writeObject和readObject 寫入和讀取二進制數據默認所用的編碼格式是AMF 3 規範。通過設置FileStream.objectEncoding屬性,你可以使用AMF 0 格式,下面的例子保存用戶信息到擴展名爲.user的文件上:

+展開
-XML
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxmllayout="vertical">
<mx:Script>
<![CDATA[
import com.oreilly.flexcookbook.UserData;
private var userData:UserData = new UserData();
private static const EXT:String = ".user" ;
private function submitHandler():void {
userData.firstName = firstField.text;
userData.lastName = lastField.text;
userData.age = ageField.value;
saveUserData();
}
private function saveUserData():void
{
var fnm:String = userData.firstName + "_"+userData.lastName + EXT;
var file:File =File.desktopDirectory.resolvePath( fnm );
var stream:FileStream = new FileStream();
stream.open( file, FileMode.WRITE );
stream.writeObject( userData );
stream.close();
}

]]>
</mx:Script>
<mx:Form>
<mx:FormItem label="First Name:">
<mx:TextInput id="firstField"
change="{submitBtn.enabled = firstField.text != ''}"/>

</mx:FormItem>
<mx:FormItem label="Last Name:">
<mx:TextInput id="lastField"
change="{submitBtn.enabled = lastField.text != ''}"/>

</mx:FormItem>
<mx:FormItem label="Age:">
<mx:NumericStepper id="ageFieldminimum="18maximum="110" />
</mx:FormItem>
<mx:Button id="submitBtnlabel="submitenabled="falseclick="submitHandler();" />
</mx:Form>
</mx:WindowedApplication>


當用戶輸入並提交信息後,submitHandler事件處理器被調用,UserData對象被更新,接着調用saveUserData方法。在saveUserData方法中,用UserData實例的firstName和lastName屬性組成文件路徑,文件被保存到桌面上,擴展名爲.user。當反序列化時,文件被再次打開,對象屬性值將被會恢復。下面的例子擴展了之前的程序,提供對打開.user文件的支持:

+展開
-XML
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxmllayout="vertical">
<mx:Script>
<![CDATA[
import com.oreilly.flexcookbook.UserData;
[Bindable]
private var userData:UserData = new UserData();
private var file:File = File.desktopDirectory;
private var filter:FileFilter = new FileFilter("User File""*.user");
private static constEXT:String = ".user";
private function submitHandler():void{
userData.firstName = firstField.text;
userData.lastName = lastField.text;
userData.age = ageField.value;
saveUserData();
}
private function saveUserData():void {
var fnm:String = userData.firstName + "_" + userData.lastName + EXT;
var file:File = File.desktopDirectory.resolvePath( fnm );
var stream:FileStream = new FileStream();
stream.open( file, FileMode.WRITE );
stream.writeObject( userData );
stream.close();
}
private function openHandler():void {
file.browseForOpen( "Open User", [filter] );
file.addEventListener( Event.SELECT, selectHandler );
}
private function selectHandler( evt:Event ):void {
var stream:FileStream = new FileStream();
stream.open( file, FileMode.READ );
userData = stream.readObject();
}

]]>
</mx:Script>
<mx:Form>
<mx:FormItem label="First Name:">
<mx:TextInput id="firstField"
text="{userData.firstName}"
change="{submitBtn.enabled = firstField.text != ''}"/>

</mx:FormItem>
<mx:FormItem label="Last Name:">
<mx:TextInput id="lastField"
text="{userData.lastName}"
change="{submitBtn.enabled = lastField.text != ''}"/>

</mx:FormItem>
<mx:FormItem label="Age:">
<mx:NumericStepper id="ageFieldvalue="{userData.age}minimum="18maximum="110" />
</mx:FormItem>
<mx:Button id="submitBtnlabel="submitenabled="falseclick="submitHandler();"
/>

</mx:Form>
<mx:HRule width="100%" />
<mx:Button label="openclick="openHandler();" />
</mx:WindowedApplication>


當用戶點擊open按鈕時,File.browseForOpen方法會打開一個對話框,並設置了過濾器只顯示.user 擴展名的文件。當一個文件被選中後, selectHandler 方法被調用, 通過FileStream.readObject方法將文件讀入到緩衝區,readObject方法將反序列化UserData對象,通過數據綁定將保存的數據顯示到表單。

FileStream.writeObject和FileStream.readObject方法提供了很多方法用於序列化數據對象到文件系統上。通過[RemoteClass]元數據標籤註冊類即可用AMF將類進行編碼爲二進制格式。

如果你是從文本文件中處理載入和解析鍵--值對自定義對象,那麼序列化自定義對象將大大減少開發開銷

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章