Search code examples
actionscript-3flashairfilestream

Error hanlder for FileStream - AS3 AIR


I'm saving an object to a file using FileStream. The object I'm saving has variables in it:

var saveObj:Object = new Object()
saveObj['FirstName']="Georges"
saveObj['LastName']="St-Pierre"

MY question is this: How do I make an error handler for a variable missing when I load the File? For example 'Firstname' is missing. How do I do that? This is the code I have but it doesn't work.

private function F_loadData():void {
    folder = File.documentsDirectory.resolvePath("saved projects");
    var file:File = folder.resolvePath("mySave.adktf");
    var stream:FileStream = new FileStream();
    stream.addEventListener(Event.COMPLETE, completeHandler); 
    stream.addEventListener(ProgressEvent.PROGRESS, progressHandler); 
    stream.addEventListener(IOErrorEvent.IO_ERROR, errorHandler); 
    stream.openAsync(file, FileMode.READ);
    var myLoadedObj:Object = stream.readObject(); 
    stream.close()
    trace(myLoadedObj.MiddleName)
}
private function completeHandler(event:Event):void { 
    trace("load Complete")//not final. Just for testing
} 

private function progressHandler(event:ProgressEvent):void { 
    // ... 
} 
//I was hoping the error would call this function
private function errorHandler(event:IOErrorEvent):void { 
    trace("Error found")//not final. Just for testing
} 

trace(myLoadedObj.MiddleName) should return an error and i was hoping that it would call the error Handler function that I made, but it didn't. It still returns an error. So how and what type of error handler should I use?


Solution

  • Since you are opening your file asynchronously, you need to wait to use readObject until after the complete event.

    The error handler you've defined is only applicable to the loading of the file. SO if there is a problem opening the file the error handler will be called, any other kind of error is outside that scope.

    Try something like this:

    private var stream:FileStream;
    private function F_loadData():void {
        folder = File.documentsDirectory.resolvePath("saved projects");
        var file:File = folder.resolvePath("mySave.adktf");
    
        if(file.exists){
            stream = new FileStream();
            stream.addEventListener(Event.COMPLETE, completeHandler); 
            stream.addEventListener(ProgressEvent.PROGRESS, progressHandler); 
            stream.addEventListener(IOErrorEvent.IO_ERROR, errorHandler); 
            stream.openAsync(file, FileMode.READ);
            //now wait for it to load
        }else{
            //file doesn't exist, do something
        }
    }
    private function completeHandler(e:Event):void { 
        trace("load Complete")//not final. Just for testing
    
        var myLoadedObj:Object = stream.readObject(); 
        stream.close();
        stream = null;
    
        if(!myLoadedObj.MiddleName || myLoadedObj.MiddleName == ""){
            //Middle name is missing or empty, do something
        }
    
        if(!myLoadedObj.FirstName || myLoadedObj.FirstName == ""){
           //First name is missing or empty, do something
        }
    } 
    

    You may be better suited to using a custom class for your save object, something like this:

    package {
        public class SaveObject {
            public var middleName:String;
            public var lastName:String;
            //any other properties
    
            public function validate():Boolean {
                //write some validation
    
                //if you want lazy validation, you could do this: (untested)
                for (var i in obj){
                    if(obj[i] is String && (obj[i] == null || obj[i] == "")){
                        return false;
                    }
                }
                return true;
            }
        }
    }
    

    Then, you can do this: (in your constructor)

    flash.net.registerClassAlias("SaveData",SaveData);
    

    Then you can do the following:

    var mySaveData:SaveData = new SaveData();
    //set properties
    
    stream.writeObject(mySaveData);
    
    
    //then later
    var mySaveData:SaveData = stream.readObject();
    
    if(!mySaveData.validate()){
        //do something, it's invalid
    }