Home > Flex & AIR Archive

Flex & AIR Archive

解決例: 「ファイルから操作とエンティティを取得できません」 - Autoloader.php

釈然としない解決法ですが、よければご参照下さい。

error_require_autoloader

事象

Flex Builder 4でPHPとのデータコネクション設定を行う際に上図のエラーが発生。
使用したサンプルチュートリアル:
connect to data - Flex Test Drive | Adobe Developer Connection

エラーメッセージ

Zend Framework が正しくインストールされていて、プロジェクトの出力フォルダーにある amf_config.ini ファイルでパラメーター "amf.production" が true に設定されていないことを確認してください。
Warning: Error parsing C:\Program Files (x86)\VertrigoServ\www\TestDrive\TestDrive-debug/amf_config.ini on line 5 in C:\Program Files (x86)\VertrigoServ\www\TestDrive\TestDrive-debug\gateway.php on line 12

Warning: require_once(Zend/Loader/Autoloader.php) [function.require-once]: failed to open stream: No such file or directory in C:\Program Files (x86)\VertrigoServ\www\TestDrive\TestDrive-debug\gateway.php on line 27

Fatal error: require_once() [function.require]: Failed opening required 'Zend/Loader/Autoloader.php' (include_path='.;C:\Program Files (x86)\VertrigoServ\Smarty;C:/Program Files/ZendFramework/library') in C:\Program Files (x86)\VertrigoServ\www\TestDrive\TestDrive-debug\gateway.php on line 27

amf_config.ini

[zend]
;set the absolute location path of webroot directory, example:
;Windows: C:\apache\www
;MAC/UNIX: /user/apache/www
webroot =C:/Program Files (x86)/VertrigoServ/www

;set the absolute location path of zend installation directory, example:
;Windows: C:\apache\PHPFrameworks\ZendFramework\library
;MAC/UNIX: /user/apache/PHPFrameworks/ZendFramework/library
;zend_path =

[zendamf]
amf.production = false
amf.directories[]=TestDrive/services

gateway.php

<?php
ini_set("display_errors", 1);
$dir = dirname(__FILE__);
$webroot = $_SERVER['DOCUMENT_ROOT'];
$configfile = "$dir/amf_config.ini";

//default zend install directory
$zenddir = $webroot. '/ZendFramework/library';

//Load ini file and locate zend directory
if(file_exists($configfile)) {
	$arr=parse_ini_file($configfile,true);
	if(isset($arr['zend']['webroot'])){
		$webroot = $arr['zend']['webroot'];
		$zenddir = $webroot. '/ZendFramework/library';
	}
	if(isset($arr['zend']['zend_path'])){
		$zenddir = $arr['zend']['zend_path'];
	}
}

//
// Setup include path
	//add zend directory to include path
set_include_path(get_include_path().PATH_SEPARATOR.$zenddir);
// Initialize Zend Framework loader
require_once 'Zend/Loader/Autoloader.php';

include_pathの'.;C:\Program Files (x86)\VertrigoServ\Smarty;C:/Program Files/ZendFramework/library'から、'Zend/Loader/Autoloader.php'を開けませんというエラー。

include_path 先のフォルダ構成を確認すると確かに'Zend/Loader/Autoloader.php'がないのでエラーが発生するのは分かる。

解決法

amf_config.iniファイル中のwebrootパラメータをコメントアウトすると正常に設定が完了。
変更前

webroot =C:/Program Files (x86)/VertrigoServ/www

変更後

;webroot =C:/Program Files (x86)/VertrigoServ/www

原因

本来はC:/Program Files (x86)/VertrigoServ/www/ZendFramework/library/Zend/Loader/Autoloader.phpを参照をすべき所を、C:/Program Files/ZendFramework/library/Zend/Loader/Autoloader.phpを参照しようとしてエラーとなった。
webroot =C:/Program Files (x86)/VertrigoServ/wwwのはずが、どこで書き換わったのかな?

今回はサンプルを走らせるのを優先したので、原因究明はここで止めています><;

追記 - 2010/07/26

以下のようなエラーメッセージが出力された場合も、上記の原因と同一である場合があります。

error_require_autoloader2

Send failed
Channel.Connect.Failed error NetConnection.Call.BadVersion: :
url: 'http://localhost/TestDrive_add_charts_PHP/gateway.php'

ご参考まで。

AIR: Webサーバ、Socketの接続状況を検知 - URLMonitor、SocketMonitorクラス

任意のアドレスのWebサイト[サービス]のネットワーク状況を検知するURLMonitorと、任意のサーバ+ポートに接続可能か否かを検知するSocketMonitorクラスの動作サンプルを下記に示します。

ソースコード

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
  applicationComplete="startup()">
  <mx:Script>
    <![CDATA[
    import air.net.SocketMonitor
    import air.net.URLMonitor;
    import flash.net.URLRequest;
    import flash.events.StatusEvent;

    private var SERVER_URL:String = "http://www.yukun.info/";
    private var SOCK_ADRR:String = "yukun.info";
    private var PORT:int = 6667;
    private var INTERVAL_TIME:int = 3000; // ms
    private var serviceMonitor:URLMonitor = null;
    private var socketMonitor:SocketMonitor = null;

    private function startup():void {
      var endpoint:URLRequest = new URLRequest(SERVER_URL);
      serviceMonitor = new URLMonitor(endpoint);
      serviceMonitor.addEventListener(StatusEvent.STATUS, onStatusEvent);
      serviceMonitor.pollInterval = INTERVAL_TIME;
      serviceMonitor.start();

      socketMonitor = new SocketMonitor(SOCK_ADRR, PORT);
      socketMonitor.addEventListener(StatusEvent.STATUS, onSocketStatusChange);
      socketMonitor.pollInterval = INTERVAL_TIME;
      socketMonitor.start();
    }

    // ネットワークサービスの状態の検知
    private function onStatusEvent(e:StatusEvent):void {
      var date:Date = new Date();
      trace(date.toLocaleTimeString());
      trace(SERVER_URL + "に" + (serviceMonitor.available ? "接続可" : "切断中"));
    }

    private function onSocketStatusChange(e:StatusEvent):void {
      trace(SOCK_ADRR + "のポート" + PORT + "は" +
        (socketMonitor.available ? "接続可" : "切断中"));
    }
    ]]>
  </mx:Script>
</mx:WindowedApplication>

実行結果


http://www.yukun.info/に接続可

yukun.infoのポート6667は切断中

URLMonitorはネットワーク状況を検知する為にサーバへGETリクエストを送出して、レスポンスのステイタスコードを確認して判断しているようです↓。

リファレンス

AIR: SQLiteでデータの挿入と検索 - SQLConnection、SQLStatementクラス

AIRアプリケーションからSQLiteのDBにアクセスするには主にSQLConnectionとSQLStatementクラスを用います。基本的な処理の流れは、

  1. SQLConnection#openAsync(<Fileオブジェクト>, <モード>)でDBに接続
  2. SQLStatement#textプロパティにSQL文を代入しexecute()で実行
  3. その際、フィールド値はSQLStatement#parameters["@<定義されたパラメータ>"]で代入する
  4. SELECT文の検索結果データははSQLStatement#getResult()で取得
  5. 結果データの型はSQLResultで、データそのものはdataプロパティ(Array型)に入っている。e.g. <SQLResult>.data[i].<フィールド名>

下のプログラムはDBに接続してテーブルの作成、レコードの追加、検索を行うサンプルです。

ソースコード

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute" creationComplete="dbConnect()">
<mx:Script>
  <![CDATA[
  import flash.data.SQLConnection;
  import flash.filesystem.File;
  import flash.events.SQLErrorEvent;
  import flash.events.SQLEvent;

  private var conn:SQLConnection;
  private var dbFile:File;
  private var sql:SQLStatement;

  // DBに接続
  private function dbConnect():void {
    conn = new SQLConnection();
    conn.addEventListener(SQLEvent.OPEN, onDBOpen);
    conn.addEventListener(SQLErrorEvent.ERROR, onDBError);
    dbFile = File.desktopDirectory.resolvePath("test01.db");
    trace("フィアルは存在" + (dbFile.exists ? "します。:" : "しません。") + dbFile.nativePath);
    conn.openAsync(dbFile, SQLMode.CREATE);
  }

  // 接続完了
  private function onDBOpen(e:SQLEvent):void {
    trace("Connect DB");
    conn.removeEventListener(SQLEvent.OPEN, onDBOpen);
    conn.removeEventListener(SQLErrorEvent.ERROR, onDBError);
    createTable(); // テーブルを作成
  }

  private function onDBError(e:SQLErrorEvent):void {
    trace("Can't connect DB: " + e.error.message);
    trace("Error detals: " + e.error.details);
  }

  // テーブルを作成する関数
  private function createTable():void {
    sql = new SQLStatement();
    sql.sqlConnection = conn;
    var sqlTxt:String = "CREATE TABLE IF NOT EXISTS addresses " +
        "(id INTEGER PRIMARY KEY, name TEXT, age INTEGER)";
    sql.text = sqlTxt;
    sql.addEventListener(SQLEvent.RESULT, onCreate);
    sql.addEventListener(SQLErrorEvent.ERROR, onCreateError);
    sql.execute();
  }

  // テーブル作成完了
  private function onCreate(e:SQLEvent):void {
    trace("Can create table");
    sql.removeEventListener(SQLEvent.RESULT, onCreate);
    sql.removeEventListener(SQLErrorEvent.ERROR, onCreateError);
    insertData(); // データを挿入
  }

  private function onCreateError(e:SQLErrorEvent):void {
    trace("Can't create table: " + e.error.message);
    trace("Error details: " + e.error.details);
  }

  private function insertData():void {
    sql = new SQLStatement();
    sql.sqlConnection = conn;
    var sqlTxt:String = "INSERT INTO addresses (id, name, age) " +
      "VALUES (@id, @name, @age)";
    sql.text = sqlTxt;
    sql.parameters["@id"] = 1;
    sql.parameters["@name"] = "名無し";
    sql.parameters["@age"] = 18;
    sql.addEventListener(SQLEvent.RESULT, onInsert);
    sql.addEventListener(SQLErrorEvent.ERROR, onInsertError);
    sql.execute();
  }

  // データ挿入完了
  private function onInsert(e:SQLEvent):void {
    trace("Can insert data");
    sql.removeEventListener(SQLEvent.RESULT, onInsert);
    sql.removeEventListener(SQLErrorEvent.ERROR, onInsertError);
    selectData(); // データを検索
  }

  private function onInsertError(e:SQLErrorEvent):void {
    trace("Can't insert data: " + e.error.message);
    trace("Error details: " + e.error.details);
  }

  private function selectData():void {
    sql = new SQLStatement();
    sql.sqlConnection = conn;
    var sqlTxt:String = "SELECT * FROM addresses";
    sql.text = sqlTxt;
    sql.addEventListener(SQLEvent.RESULT, onSelect);
    sql.addEventListener(SQLErrorEvent.ERROR, onSelectError);
    sql.execute();
  }

  // 検索結果を取得完了
  private function onSelect(e:SQLEvent):void {
    trace("Can select data");
    sql.removeEventListener(SQLEvent.RESULT, onSelect);
    sql.removeEventListener(SQLErrorEvent.ERROR, onSelectError);
    var result:SQLResult = sql.getResult();
    var num:int = result.data.length;
    var id:int;
    var name:String;
    var age:String;

    for (var i:int = 0; i < num; i++) {
      var row:Object = result.data[i];
      id = row.id;
      name = row.name;
      age = row.age;
      var str:String = "id=" + id + ", name=" + name + ", age=" + age;
      trace(str);
    }
  }

  private function onSelectError(e:SQLErrorEvent):void {
    trace("Can't select data: " + e.error.message);
    trace("Error details: " + e.error.details);
  }

  ]]>
</mx:Script>

</mx:WindowedApplication>

実行結果

フィアルは存在しません。/Users/yukun/Desktop/test01.db
Connect DB
Can create table
Can insert data
Can select data
id=1, name=名無し, age=18

リファレンス

AIR: テキストファイルに書き込み - openAsync()、writeMultiByte()

AIR: テキストファイルに書き込み

AIRコンポーネントではローカルのファイルにアクセスすることができます。下記のコードは日本語を含むマルチバイトの文字列をテキストファイルに書き込む処理をします。

処理の手順

  1. FileStream#openAsync()かopen()メソッドの引数にFileインスタンスとFileModeのプロパティを設定して実ファイルのパイプに接続
  2. FileStream#writeMultiByte()でファイルに書き込み
  3. FileStream#close()でストリームを閉じる

ソースコード

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" title="シンプルテキストメイカー">
<mx:Script>
  <![CDATA[
  import mx.controls.Alert;

  private var choDir:File = File.documentsDirectory; // ダイアログの初期ディレクトリ
  private var saveFile:File;
  private var stream:FileStream;

  private function onSaveFileBut():void {
    choDir.addEventListener(Event.SELECT, onSelectSaveFile);
    choDir.browseForSave("テキストファイルに保存");
  }

  private function onSelectSaveFile(e:Event):void {
    saveFile = e.target as File; // 選択されたファイル
    choDir.removeEventListener(Event.SELECT, onSelectSaveFile);
    try {
      stream = new FileStream();
      stream.addEventListener(IOErrorEvent.IO_ERROR, onIOErrorWriteFile);
      stream.openAsync(saveFile, FileMode.WRITE); // 書き込みmodeで開く(フツーのopen()でもOK)
      var str:String = txtArea_.text;
      // 改行文字と文字コードをOS標準のものに置き換えて書き込み
      str = str.replace(/\n/g, File.lineEnding);
      stream.writeMultiByte(str, File.systemCharset); // 実際に書き込み
    } catch (err:IOError) {
      progLab_.text = "IOError : " + err;
    } finally {
      if (stream != null) {
        stream.close();
      }
    }
  }

  // ファイル書き込みに失敗した場合
  private function onIOErrorWriteFile(e:IOErrorEvent):void {
    Alert.show("ファイルの書き込みに失敗", "エラー", Alert.OK, this);
    if (stream != null) {
      stream.close();
    }
  }
  ]]>
</mx:Script>
  <mx:VBox x="0" y="0" height="100%" width="100%">
    <mx:HBox width="100%">
      <mx:Button label="ファイルに保存" id="saveBut_" click="onSaveFileBut();"/>
      <mx:Label id="progLab_"/>
    </mx:HBox>
    <mx:TextArea width="100%" height="100%" id="txtArea_"/>
  </mx:VBox>
</mx:WindowedApplication>

リファレンス

AIR: テキストファイルを非同期に読み込む - openAsync()、readMultiByte()

AIR: テキストファイル読み込みの実行結果

AIRコンポーネントではローカルのファイルにアクセスすることができます。下記のコードは日本語を含むマルチバイトのテキストファイルを読み込み、画面い表示する処理を行います。

大まかな手順

  1. FileStreamのコンストラクタの引数に対象のファイルへのパスが設定されたFileインスタンスを渡す。
  2. FileStream#openAsyncで実ファイルへのパイプ接続。
  3. この時、非同期の読み込み完了/エラーを取得するためにイベントを登録しておく。
  4. 実際の文字の読み取り(どれだけ読むか、文字コードの変換など)はFileStream#readMultiByteで行う。
  5. ストリームのインスタンスには接続時にpositionプロパティ(何処読んでいるかのポインタみたいなもの)からファイル末尾までのサイズ(bytesAvailable)を取得してるので、読み込みサイズにそれを指定。
  6. FileStream#close()でストリームを閉じる

ソースコード

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
  title="テキストビュワー">
  <mx:Script>
    <![CDATA[
    import flash.filesystem.*;
    import mx.events.*;
    import mx.controls.Alert;

    private var choDir:File = File.documentsDirectory; // 開くディレクトリを指す
    private var curFile:File; // 選択されたファイル
    private var stream:FileStream;

    private function onOpenFileBut():void {
      choDir.addEventListener(Event.SELECT, onSelectFile);
      choDir.browseForOpen("開く"); // ファイル選択ダイアログの表示
    }

    // ファイルが選択されたイベント
    private function onSelectFile(e:Event):void {
      txtArea_.text = "";
      stream = new FileStream();
      curFile = e.target as File;
      stream.addEventListener(Event.COMPLETE, onCompleteReadFile);
      stream.addEventListener(IOErrorEvent.IO_ERROR, onIOErrorReadFile);
      stream.addEventListener(ProgressEvent.PROGRESS, onProgReadFile);
      stream.openAsync(curFile, FileMode.READ); // 非同期読み込み
      curFile.removeEventListener(Event.SELECT, onSelectFile);
    }

    private function onCompleteReadFile(e:Event):void {
      try {
        // OS標準の文字コードで読み込み
        var str:String = stream.readMultiByte(stream.bytesAvailable, File.systemCharset);
        // OS標準の改行文字への変換
        var pat:RegExp = new RegExp(File.lineEnding, "g");
        str = str.replace(pat, "n");
        txtArea_.text = str; // テキストエリアに表示
        stream.removeEventListener(Event.COMPLETE, onCompleteReadFile);
        stream.removeEventListener(IOErrorEvent.IO_ERROR, onIOErrorReadFile);
        stream.removeEventListener(ProgressEvent.PROGRESS, onProgReadFile);
      } catch (err:Error) {
        progLab_.text = "IOError: " + err;
      }
      finally {
        // パイプのクローズ
        if (stream != null) {
          stream.close();
        }
      }
    }

    private function onIOErrorReadFile(e:IOErrorEvent):void {
      Alert.show("ファイルを読み込み不可", "Error", Alert.OK, this); // 第4引数には親オブジェトを渡す
      if (stream != null) {
        stream.close();
      }
    }

    private function onProgReadFile(e:ProgressEvent):void {
      progLab_.text = "Progress: " +  e.bytesLoaded + " / " + e.bytesTotal + " bytes";
    }
    ]]>
  </mx:Script>
  <mx:VBox x="0" y="0" height="100%" width="100%">
    <mx:HBox width="100%">
      <mx:Button label="ファイルを開く" id="openBut_" click="onOpenFileBut();"/>
      <mx:Label id="progLab_"/>
    </mx:HBox>
    <mx:TextArea width="100%" height="100%" id="txtArea_"/>
  </mx:VBox>

</mx:WindowedApplication>

リファレンス

Home > Flex & AIR Archive

バックナンバー
最近のコメント
最近のトラックバック
メタ情報

Return to page top