忍者ブログ
研究室生活のメモ・・・だった過去の遺産。移転先→http://negimochix2.blogspot.com/
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

都合上,XMLを自由に読み書きする必要が出てきた.

そこで,FileStreamクラス(AIRで追加されたファイルの読み書き用クラス)を使い,
XMLのメソッド1つで,非同期に読み書きをするXMLManagerクラスを作ってみた.

package {
	import flash.events.EventDispatcher;
	import flash.events.OutputProgressEvent;
	import flash.events.Event;
	import flash.filesystem.File;
	import flash.filesystem.FileMode;
	import flash.filesystem.FileStream;
	
	/** XML用クラス
	 * @auther kusamochi
	 * @extend EventDispatcher
	 */
	public class XMLManager extends EventDispatcher {
		public static const READ_COMPLETE:String = "read_complete";
		public static const READ_CLOSE:String = "read_close";
		
		public static const WRITE_PROGLESS:String = "write_progress";
		public static const WRITE_CLOSE:String = "write_close";
		
		private var _xml:XML;  // [read]xmlファイルの実体
		private var fileStream:FileStream;
		private var _mode:String;
		
		//コンストラクタ
		public function XMLManager() {
			_mode = "NormalMode";
		}
		
		// 明示的な参照解除メソッド
		public function deleteReference():void {
			if(fileStream) {
				if(_mode == "ReadMode") {
					fileStream.removeEventListener(Event.COMPLETE, readStreamCompleteHandler);
					fileStream.removeEventListener(Event.CLOSE, readStreamCloseHandler);
				}
				else if(_mode == "WriteMode") {
					fileStream.removeEventListener(OutputProgressEvent.OUTPUT_PROGRESS, writeStreamOutputProgressHandler);
					fileStream.removeEventListener(Event.CLOSE, writeStreamCloseHandler);
				}
			}
		}
		
		// ファイル読み込み
		public function readXML(file:File):void {
			trace("XMLManager::readXML");
			trace("Reading : " + file.nativePath);
			
			_mode = "ReadMode";
			fileStream = new FileStream();
			fileStream.addEventListener(Event.COMPLETE, readStreamCompleteHandler);
			fileStream.addEventListener(Event.CLOSE, readStreamCloseHandler);
			fileStream.openAsync(file, FileMode.READ);
		}
		
		// ファイル出力
		public function writeXML(file:File):void {
			trace("XMLManager::writeXML");
			trace("Writing : " + file.nativePath);
			
			_mode = "WriteMode";
			fileStream = new FileStream();
			fileStream.addEventListener(OutputProgressEvent.OUTPUT_PROGRESS, writeStreamOutputProgressHandler);
			fileStream.addEventListener(Event.CLOSE, writeStreamCloseHandler);
			fileStream.openAsync(file, FileMode.WRITE);
			fileStream.writeMultiByte(_xml.toXMLString(), File.systemCharset);
		}
		
		public function printXML():void {
			trace(_xml.toXMLString());
		}
		
		// EventHandler ///////////////////////////////////////////////////////////
		// Read  ----------------------------------------
		// Readストリームがクローズ
		private function readStreamCloseHandler(event:Event):void {
			trace("XMLManager::readStreamCloseHandler");
			fileStream.removeEventListener(Event.COMPLETE, readStreamCompleteHandler);
			fileStream.removeEventListener(Event.CLOSE, readStreamCloseHandler);
			_mode = "NormalMode";
			
			// カスタムイベントを配信する
			super.dispatchEvent(new Event(READ_CLOSE));
		}
		
		// 読み込み完了
		private function readStreamCompleteHandler(event:Event):void {
			trace("XMLManager::readStreamCompleteHandler");
			var tmpStr:String = fileStream.readMultiByte(fileStream.bytesAvailable, File.systemCharset);
			fileStream.close();
			_xml = new XML(tmpStr);
			
			// カスタムイベントを配信する
			dispatchEvent(new Event(READ_COMPLETE));
		}
		
		// write --------------------------------------
		// Writeストリームがクローズ
		private function writeStreamCloseHandler(event:Event):void {
			trace("XMLManager::writeStreamCloseHandler");
			fileStream.removeEventListener(OutputProgressEvent.OUTPUT_PROGRESS, writeStreamOutputProgressHandler);
			fileStream.removeEventListener(Event.CLOSE, writeStreamCloseHandler);
			_mode = "NormalMode";
			
			// カスタムイベントを配信する
			super.dispatchEvent(new Event(WRITE_CLOSE));
		}
		
		// Write進行中
		private function writeStreamOutputProgressHandler(event:OutputProgressEvent):void {
			trace("XMLManager::writeStreamOutputProgressHandler");		
			if(event.bytesPending == 0){
				fileStream.close();
			}
			
			// カスタムイベントを配信する
			super.dispatchEvent(new OutputProgressEvent(WRITE_PROGLESS));
		}
		
		// getter ////////////////////////////////////////////////////
		// XMLオブジェクトを返す(他のクラスからのアクセスに対応)
		public function get xml():XML {
			return _xml;
		}
		
		// mode
		public function get mode():String {
			return _mode;
		}
		
		// setter //////////////////////////////////////////////
		public function set xml(setXML:XML) {
			_xml = setXML;
		}
		
	}
}
FileStreamクラスのファイルオープンには,openメソッド,openAsyncメソッドの2つがある.
openメソッドを使うと,それ以降のFileStreamの処理は,その行の処理が終わるまで次の行を実行しない
でも,それだと,ロード対象のサイズが大きくなった場合などに遅延が起きてしまう.

それを避けたいのなら,openAsyncメソッドでファイルオープンする.
openAsyncにすると,各処理ごとにイベントを発行する.
つまり,FileStreamのオブジェクトにaddEventListenerしとけば,読み込み終わりとか判定できるわけです.

そこで,上記のXMLManagerでは,各イベントを利用してMXLの読み書きを行い,さらにカスタムイベントを配信する.
EventDispatcherを継承したのはこのため.


これ,作るときに気づいたんだが,
READモードだとcompleteイベント発生するのに,WRITEモードではcompleteイベント発生しないんだね.
最初気づかずにWRITEモードでもcompleteでファイルクローズしてたから,
イベント自体が発生してないからクローズされていないってことで,
上書き時にエラー出て散々ハマりましたw

しょうがないんで,OutputProgressイベント(出力中に定期的に発生するイベント)を使って,
bytesPending(残りの書き込みバイト数)がゼロになったときにクローズするようにしてみた.

PR
この記事にコメントする
お名前
タイトル
メールアドレス
URL
コメント
パスワード   Vodafone絵文字 i-mode絵文字 Ezweb絵文字
この記事へのトラックバック
この記事にトラックバックする:
Infomation
くさもち 【中の人】
・くさもち
・ボカロ廃大学院生
・βからのニコ厨
・もちろん非リア充
・ミクZ4 第二期個人スポンサー

【メール】
・negimochi.tabetai(゚Д゚)gmail.com
(゚Д゚)→@

【その他やってるもの】
Twitter

・これは痛いピアプロ
・過去の遺産smart.fm

【作ったもの】
・製作に参加したDTX GDPメインサイト
で,実際に作ったIRページ
カレンダー
10 2024/11 12
S M T W T F S
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Heartsnative
『Heartsnative/MOSAIC.WAV×鶴田加茂 feat.初音ミク』応援中!
VOCALOID Ranking Watcher
新曲は常にチェックすべし。
真・フルみっくすプレイヤー
おすすめ記事
jubeat ripples
今更やってみる