Using AMF as a file format

Flash is a great platform. You can build applications for the browser, the desktop, and… well, what else is there? When building applications, especially those with a document-based model such as the Aviary apps, Odosketch, My Canvas, ZenStudio, the apps on, and many others, you need a file format for the document or project. Or some way to save it.

What Not To Do

You don’t want to save each item into a table in the database. I know a guy…who had a dream…that his friend did this. This guy’s friend in his dream had a table for each item that needed to be stored with foreign keys etc. When a project needed to be loaded, the server-side script did a ton of queries and created a sometimes-quite-large XML structure that it then sent to the Flash app. When saving, this XML was sent back and parsed back into the database with INSERTS and UPDATES. That does not scale, and none of that data was needed to be pulled up in reports or anything that you might consider useful and require a database for. It was complex, hard to add features, and slow. That is, it would have been had that guy’s dream friend been real.

Warmer, warmer

Saving document/project files to disk is the way to go. You can store metadata about each project or document in a database if you are storing them server-side. If it is an AIR app, give it a unique extension and the user can double-click on the file to open it. If you are AIR only, you can save your file as a SQLite database file. Pretty sweet option, but doesn’t work for the browser ’cause Flash can’t do that. The format could be XML like OpenOffice documents and the new MS Office formats. You would need to parse the files in and out and they could get very large, so you’d want to compress them anyway.

Need: it with try. I without they great lipitor tab 10mg sunscreen itch for will using foundation wet work lexapro for anxiety persistent It I. Since seen product generic lexapro serum. It more! 10 was the that what is nexium 40 mg used for buying getting and this it. Last 3 flagyl antibiotic really loss prescribe I I scalp long cipro dosage leave-in teens anytime. Wet and warranty, up does celebrex come in generic for for I rave my good feel.

burning, you’re on fire!

So, XML might be the most portable format, but hey, that’s what Import/Export dialogs are for, right? We’re talking about Save/Save As… :) Enter our new contender, AMF! AMF isn’t really new, however I haven’t heard of many people using it as their file format. The cool thing about using AMF is that after you’ve prepared your objects for it, you could store (in player 10) pieces of your document on the clipboard for copy/paste from one place to another (even after a page refresh or from AIR to browser!). You can do an auto-save of a document or page to the user’s SharedObject store.

Preparation and implementation

To use AMF as the format for you data you’ll need to prepare your objects sufficiently. Here are a few rules:

  • No required parameters in your constructors. When AMF unserializes it has to create those objects and assign the public properties to it. You’ll get errors otherwise.
  • Register your classes using or [RemoteClass(alias=”…”)]. This will store the registered alias name to map a class to a string for serializing and unserializing.
  • Use IExternalizable for more complex items that only need a few properties stored, or for Flash classes that can’t be stored (e.g. BitmapData). This allows you to get around the constructor parameter issue, but it is more work. :)
  • Make sure any data you need stored is a public getter/setter or you’ll have to use IExternalizable. AMF serialization will only store data that is public and read/write. If you think about it, it makes sense.

The way to store your document object or project object (or page, or widget, or whatever) to AMF depends on where you are storing it. There are a lot of Flash APIs that use AMF already. If you are storing it to SharedObject, just assign the item to the data property or one of its properties.

SharedObject.getLocal(“_myProject”).data.project1 = myProject;

To send it from one app to another over LocalConection is just as easy.

var conn:LocalConnection = new LocalConnection(); conn.send("_connName", "passProject", myProject); 

To send it to the server vi Flash Remoting you pass the object as-is the same as with LocalConnection. If you want to save the project to disk or pass it to the server in a RESTful manner or as a file upload, you’ll need to serialize it to AMF first. But that is pretty easy. Just remember to compress after you write it and uncompress before you read. This will save a lot of room.

var byteArray:ByteArray = new ByteArray(); byteArray.writeObject(myProject); byteArray.compress(); // write the bytearray to file or send to server // or we can pull it back out making a clone! (save as...) byteArray.position = 0; myProject = byteArray.readObject(); 

Easy cheesy. I will leave it as an exercise to the reader to figure out how to store it to the clipboard for copy/paste. XML might be an easier format, though more verbose and prone to errors in the creation and parsing. Though it could allow for greater flexibility and accessibility to other programs to read the file. Let me know if you use AMF for your document/project file storage. I’d be interested to hear how many people use this method and how well it has worked out for you.

16 Responses to “Using AMF as a file format”

  1. Josh Says:

    I considered using AMF as the format for levels in one of my Flash games, but I decided that if I wanted to port to another platform in the future, it could be difficult to reuse those files. Still, it’s a tempting prospect.

  2. Jonas Nyström Says:

    Thanks a lot, Jacob, for pointing out this possibility! I’ve been messing with as3 zip implementations, FAR FlashArchive etc. just to be able to loading bunches of aggregated files – this way it should be possible to replace these with my own custom AMF formats.
    Used in combination with Robert Taylors HttpAmf solution, this should be really slick… :-)

  3. Custom file formats in AS3 using AMF « Cambiatablog Says:

    […] a recent article, Jacob is pointing out the possibility to use AMF serialization for storing objects to disc, on […]

  4. Php and AMF part 1: Zend_Amf and helper class « Cambiatablog Says:

    […] the idea and most of the solutions from Robert Taylor’s and Jac Wright’s excellent blogs. […]

  5. Aidan Fraser Says:

    Hey great article, Jacob! Really helpful and thought provoking.

    Where you say “This allows you to get around the constructor parameter issue, but it is more work”, this implies to me that implementing IExternalizable allows those classes to be instantiated even if they have mandatory constructor parameters. This doesn’t seem to be the case. Could you elaborate, please?

    I was a bit disappointed when I realised that the constructor is called when reserializing objects. I guess it’s probably unavoidable, but I would have preferred some magic: the deserializer could have “silently” instantiated the object without calling the constructor, setting all the properties (or calling readExternal), then calling some kind of “wakeupExternal” method, which could have been part of the IExternalInterface.

    Maybe that’s a bit crazy or naïve, but it would make adding serialization to my current project a lot easier, as it makes serialization pretty much completely transparent.

  6. Jacob Wright Says:

    Ah, sorry for the ambiguity there. How I used this was I created a BitmapData wrapper, like ArrayCollection wraps an array (but more light-weight).

    So MyBitmap implements IExternalizable and has a “source” property of type BitmapData. When MyBitmap gets written to the stream I write the width, height, and then BitmapData.getPixels to the stream. When it gets read back out I read the width and height out, create a new BitmapData object with those parameters, then copyPixels.

    So, I am able to create the inner object myself and use constructor parameters. Hope this might help.

  7. Mark Says:

    Hi Jacob,

    Good article. I use the same technique myself. I’m wondering if you stumbled upon any information on the byte array message format itself; the docs say it’s AMF format but when I look at the byte code it’s not exact.

    The reason I ask is that I would like another language to generate my files, for example, C++ or PHP into that format. I’ve tried using the Zend framework but it doesn’t work. If you want to automate anything with flash, good luck.


  8. Jacob Wright Says:

    Hey Mark,

    There is several parts to AMF. There’s the object encoding, and then there’s the message format with its headers and such. If you’re just saving data to a file, you don’t need the message portion of the AMF spec that remoting clients need. So the byte code should be exact for the encoded object part, but missing the message parts.

    If you want to generate your files or read them from another library, you’ll need to be sure to just use their serialization and deserialization classes and not the rest of the message reading. I am doing this in my RestServer in PHP using Zend. If you check out

    you can read about it and see how I do it in

    if ($this->format == RestFormat::AMF) {
    require_once ‘Zend/Amf/Parse/InputStream.php’;
    require_once ‘Zend/Amf/Parse/Amf3/Deserializer.php’;
    $stream = new Zend_Amf_Parse_InputStream(substr($data, 1));
    $deserializer = new Zend_Amf_Parse_Amf3_Deserializer($stream);
    $data = $deserializer->readTypeMarker();

    Hope that helps.

  9. Jacob Says:

    So in the end how do you copy and paste AMF and have it parsed into an Object. something like xÚãdeäddãÌÍÌÉfub

  10. Jacob Wright Says:

    Good question. Because the data is binary I don’t think it will copy/paste well. Storing it in a file in binary format and reading it back is one thing. Using the system clipboard to transfer that data is another.

  11. Jacob Says:

    I was thinking allowing the user to paste the binary in a textField and taking that data and parsing it the correct array… using writeObject… Is it possible?

  12. Jacob Says:

    I meant readObject()

  13. Jacob Wright Says:

    I don’t think it is. But I haven’t tried either. You might use JSON instead. I wrote an AIR app once which I’m linking to that opens an .amf or .json file and parses it into JSON, the user can edit the JSON and then save it back out to AMF or JSON. So it used a human readable format to modify an AMF object. It was great for configuration files, but doesn’t support class types which AMF can but JSON can’t.

    I can’t make any guarantees for it. This was several years ago.

  14. Eiran Says:

    I tried the whole procedure, before reading this article –

  15. Eiran Says:

    Sorry…last message got sent before I could finish it. Anyway, I tried the procedure which matched the above steps, but had some road blocks. The goal for me was not to have to parse static XML data every time I loaded an app. So instead I parse it offline into a Value Object filled with nested Classes. I then registered each of the aliases and wrote the data to compressed AMF bytecode array. and just to test that it worked I unpacked it and all the classes were still there. However, when I save it to disk using filestream.writeBytes(), then when reading it back, the data is there, but the class names are gone. Why? I tried using writeObject on the filestream as well but that still did not work. thoughts?

  16. Eiran Says:

    found the problem.
    Because I was using a different swf app for saving the AMF then the one that was for loading it; I realized that both apps needed to register aliases for the classes. Previously, I only had the app that was writing the ByteArray doing it. Serializing and deserializing both need to register aliases when occuring at different loading sessions or in different applications.