Reading and Writing your own file type with AS3 and AIR

If your building an AIR application and you want to have your own native custom file type association for your app, it is surprisingly easy to to with ActionScript 3 in air as I found out. I was unable to find any information on reading and writing custom files so I decided to post my experience here. I remembered watching a tutorial by Lee Brimelow at gotoAndLearn a while back where he showed how to decode a BMP file using ByteArrays. So I revised the tutorial and used the ideas from this to create my own file.

For this example I will create a simple graphic file containing some metadata and some bitmap data.

1. Write out the specification

The first thing you should do is map out a spec sheet for it, outlining all the data and datatypes you want to store and the order it will be written. This is important so you don’t forget later on, and if you want others to be able to use it as well. Your custom file must be read and written in the same order. I just did it in Notepad like so:

image name – String
image author – String
image width – int
image height – int
bitmapdata length – int
bitmapdata – bytearray

Note that this is a very basic file, so you could save all different data types such as Boolean, Number, String, int, uint etc.

2. Get your data into a ByteArray

To write the file first we need to create a bytearray and then using the write methods of the ByteArray class write the bits of data to it:

[cc lang=”actionscript”]

// the stuff we want to save – name, author and a bitmap – in this case I’ve created a red square 300x300px
var name:String = “a new picture”;
var author:String = “Ted Mosby”;
var bitmap:Bitmap = new Bitmap(new BitmapData(300,300,false,0xFF0000));

// convert bitmap to byte array
var bitmapBA:ByteArray = bitmap.bitmapData.getPixels();

// create a bytearray to save into file
var bytearray:ByteArray = new ByteArray();

// write the image name
bytearray.writeUTF(name);

// write author
bytearray.writeUTF(author);

// write image width and height
bytearray.writeInt(bitmap.width);
bytearray.writeInt(bitmap.height);

// write bitmap data length
bytearray.writeInt(bitmapBA.length);

// write the bitmap
bytearray.writeBytes(bitmapBA);

[/cc]

3. Write the file

Now that everything has been put into a ByteArray we can create a File object and save it to the hard drive.

[cc lang=”actionscript”]

// set a file extension – could be what ever you want it to be
var extension:String = “.abc”;

// create the file on the desktop
var myFile:File = File.desktopDirectory.resolvePath(“image” + extension);

// create a FileStream to write the file
var fs:FileStream = new FileStream();

// add a listener so you know when its finished saving
fs.addEventListener(Event.CLOSE, fileWritten);

// open the file
fs.openAsync(myFile, FileMode.WRITE);

// write the bytearray to it
fs.writeBytes(bytearray);

// close the file
fs.close();

function fileWritten(e:Event):void
{
trace(“File Saved to Desktop”);
}

[/cc]

4. Reading the file

And thats it for saving your own file types. For reading them it is pretty much the opposite of what we just did but using read methods of the File API instead of the write ones. For this example a file browse window will be initiated so the user can select a file and then load it in:

[cc lang=”actionscript”]

// create variables to hold the file data
var name:String;
var author:String;
var width:int;
var height:int;
var bmLength:int;;
var bitmapBA:ByteArray;
var bitmapData:BitmapData;
var bitmap:Bitmap;

// create a file reference
var fr:FileReferance = new FileReference();

//add events to FileReference for file select, and ready to open
fr.addEventListener( Event.SELECT, selectFile);
fr.addEventListener( Event.COMPLETE, readyToOpen);

// create a file filter so the browse window only shows our custom file type
var f:FileFilter = new FileFilter(“Custom File (*.abc)”, “*.abc”);

// initiate the browse window
fr.browse([f]);

// this event is fired when the user selects a file
function selectFile(e:Event):void
{
// load the selected file
fr.load();
}

// this event is fired when the file has finished loading
function readyToOpen(e:Event):void
{
// pass the file’s bytearray to the function below to read the data
loadFile(fr.data);
}

function loadFile(ba:ByteArray):void
{
// read the name
name = ba.readUTF();

// read the author
author = ba.readUTF();

// read the bitmap with and height
width = ba.readInt();
height = ba.readInt();

// read the bitmapdata length
bmLength = ba.readInt();

// read the bitmapdata bytearray
bitmapBA = new ByteArray();
ba.readBytes(bitmapdata, 0, bmLength);

// set the pixels of a bitmap from the loaded bitmapdata bytearray
bitmapData = new BitmapData(width, height);
bitmapData.setPixels(bitmapBA);

bitmap = new Bitmap(bitmapData);
}

[/cc]

5. Setting up Flash CS5 to associate the file type with your application

With Flash open, open up the AIR settings panel by going to File > AIR Settings and then go to the advanced tab:

(click to enlarge)

Click the + button under associated file types to add our file type, a window will popup where you can enter the file extension, icons and other information about the file type:

(click to enlarge)

Click OK to add the file association and then OK to close the AIR settings window. Now when the application is published and installed the custom file type will be associated with your app and be given the icon you defined in the AIR settings. To take this even further you can register InvokeEvents in your app so you custom files can lauch your app.

Good Luck.


Comments

9 responses to “Reading and Writing your own file type with AS3 and AIR”

  1. please tell me why did you use ‘$ba’ instead of just “ba”.Also tell me how will it differentiate between ‘name’,’author’ etc while just using one command “readUTF()”

    1. hi sam, there wasn’t any reason for using $ba instead on ba – I probably should have changed that when I posted the article for the sake of consistency. As for using readUTF() as long as you read in the correct order this will read the bytes in the same ‘chunks’ as they were written. I don’t know how it works under the hood but it just does.

      cheers,
      Ben

      1. Good job mate, it makes help a lot.

  2. After еxploгing а hаndful of
    the articles on youг web pаgе, I honеstlу like yοur ωaу of blοgging.
    I book marκеd it to mу bookmаrκ webpаgе liѕt and ωill bе checking bаck
    soon. Ρleasе viѕіt my web
    sіte аs ωell аnd tell me
    what уou think.

  3. Sebastian Avatar
    Sebastian

    Hi, that’s great! But tell me, May I register a file type that contains a swf or similar? and How? I need to do it, but the info about it is so little n internet. I’m glad I found this post! I hope you can help me, please >.<
    Thanks!

    1. I think it would be possible to write a SWF into your file. You would have to load the SWF in as a ByteArray and then write the ByteArray into the file using writeBytes. And then use readBytes to retrieve the SWF. I haven’t tried it so I don’t know whether it works but it is a start. Thanks.

  4. Nice tutorial ๐Ÿ™‚ Great solution for writing and reading bytearray.. I would like to know about compressed binary for Flex OS ( built ground system by Linux ) I am using with Zinc Studio 4.0.22. Zinc app looks like display manager for Flex OS example “fxdm”

    And i want create custom binary by writing bytearray with fzip but fzip can not create from local file into zipped file like
    Example:
    (filename.swf) () mean zipped path
    (filename_app.xml) is written by byteArray.writeObject with fzip and closed binary will read into main.swf ( fxdm binary )

    I will try again. Thanks! ๐Ÿ™‚

  5. Ayman A.Aziz Radwan Avatar
    Ayman A.Aziz Radwan

    Hi,
    please, kindly to explain for me the following lines of last section :

    bitmapBA = new ByteArray();

    ba.readBytes(bitmapdata, 0, bmLength);

    // set the pixels of a bitmap from the loaded bitmapdata bytearray

    bitmapData = new BitmapData(width, height);

    bitmapData.setPixels(bitmapBA);

    bitmap = new Bitmap(bitmapData);

    I didn’t understand well.

    thank you.

Leave a Reply