Apollo File API Overview
I was recently given the opportunity to present an introduction to the Apollo file API’s at Apollo Camp. The event itself was a huge success with an eager and inventive crowd devouring code well into the evening. During Kevin Lynch’s keynote, he mentioned that it should take Flex developers only a few minutes to get their applications into Apollo. But what comes next?
Wikipedia has an extensive definition for the term “computer file” which has a couple interesting sentences.
A computer file is a piece of arbitrary information, or resource for storing information, that is available to a computer program and is usually based on some kind of durable storage. A file is durable in the sense that it remains available for programs to use after the current program has finished. Computer files can be considered as the modern counterpart of the files of printed documents that traditionally existed in offices and libraries, which are the source of the term. (Wikipedia)
Having a durable storage area that lives on after my application has ended is a big leap forward from web applications. At its core, it is Apollo’s local file access that enables occasionally connected computing (OCC) for the web developer. It also opens the door for a new breed of applications developed using web technologies, which up to this point had required a round-trip to a server.
The file API in Apollo allows developers the ability to:
- Create and delete files and directories
- Copy and move files and directories
- List the contents of directories
- Get system information on files and directories
- Read and write binary files
- Read and write text files
- Serialize and deserialize ActionScript objects
The Apollo API’s include a new package, flash.filesystem.*, which includes only three new classes. It is these classes that make all this local file access possible. If you intend to develop Apollo applications, you should become very familiar with these classes, which are: File, FileMode and FileStream.

As you might have figured out, the File class is a representation of a file or directory on the local system. It includes the functionality to get a directory listing, find out the size of a file, when it was created and last modified and more. The FileMode class sets the stage for you to tell Apollo how it is that you want to access the designated file or directory. The FileStream class is the powerhouse containing all the methods for reading and writing data - for performing the actual IO operations.
If you’re familiar with the ByteArray class that’s already in ActionScript, then you’ll feel right at home with the FileStream object.
Now wait just a minute. Before you go off reading and writing files like a cowboy in the Wild West, you’ll want to stop and consider that Apollo allows you to deliver applications across multiple operating systems (OS). Not all operating systems represent file locations in the same fashion. If you create a file at “C:\Documents and Settings\joe\My Documents\test.txt” what does that mean to a Mac? What does “/Users/Documents/test.txt” mean to a PC?
The File class in Apollo has numerous properties that represent common file system locations in a manner that abstract the specific operating system.
| File.appStorageDirectory | Log files, cache files, preferences files |
| File.appResourceDirectory | User’s install directory |
| File.currentDirectory | Launch directory; useful for command-line arguments |
| File.desktopDirectory | User’s desktop directory |
| File.documentsDirectory | My Documents (Win), Documents (Mac) |
| File.userDirectory | User’s home directory |
Not to be worried though, if you still want to access files using a native path, you can certainly do that - just be prepared for the results. Above and beyond the common directory abstractions, Apollo also provides a means to access system resources as URI’s. Take a quick look at the following code snippet and notice the difference between the output of the native path and the URL properties.
trace( File.documentsDirectory.nativePath );
// C:\Documents and Settings\joe\My Documents
// /Users/joe/Documents
trace( File.userDirectory.url );
// file:///C:/Documents%20and%20Settings/joe
// file:///Users/joe
This additional abstraction for local file access has also extended within Apollo to offer two additional URI schemas: app-storage and app-resource.
| app-storage | var log:File = File.appStorageDirectory; log = log.resolve( “test.txt” ); trace( log.url ); // app-storage:/log.txt |
| app-resource | var install:File = new File(); install.url = “app-resource:/”; install = install.resolve( “hello-world.xml” ); trace( install.url ); // app-resource:/hello-world.xml |
This example also shows the basis for the common series of steps that you’ll take whenever you want to access the local file system. There’s the declaration of the file object, followed by a call to the File.resolve() method. This call returns a File object that you can use for the remainder of your file access. It’s pretty clear that a good amount of consideration went into local file access options. The various abstractions also create a great foundation for extension in future releases.
I know, I know, you’re getting anxious. Before we head to the boilerplate code that we’ll use for every file operation, there’s one last consideration of which we need to be aware. Apollo offers two different ways to read a file - synchronous and asynchronous. You can probably make a logic leap as to what the differences between the two are, but what does that mean to Apollo specifically?
When you choose to use the synchronous approach to working with the file system, you effectively choose to block any additional user interaction until the file is processed. It also turns out that this requires less code, which I’ve personally found very handy when writing smaller data files.
By comparison, asynchronous methods run in the background, and allow other ActionScript processes to take place at the same time. This is especially effective for those situations where the file you’re reading is larger than 1 Mb. You’ll want to use the asynchronous methods whenever there might be a delay in reading the file contents. Another example might be reading a relatively small file across a slow network.
Using the asynchronous methods also means having event listeners registered for the events you want to know about. This could be an indication that the file is open and ready for processing, or information that a certain number of bytes has been read into the buffer (i.e. random access). Using the asynchronous methods also means having more code in the form of event handlers.
There are six steps that are common to almost every file access routine you’ll ever write for Apollo.
// Setup a File object
var myFile:File = File.appStorageDirectory;
myFile = myFile.resolve( “contacts.xml” );
// Instantiate a FileStream object
var myStream:FileStream = new FileStream();
// Set the appropriate event listeners if needed
stream.addEventListener( Event.COMPLETE, doReadData );
// Open the file in the required mode
stream.openAsync( myFile, FileMode.READ );
// Various read operations in an event handler
// Close the file when you’re done with it
stream.close();
The first step is to setup the file or directory that you want to access. This can be done using the File properties mentioned earlier, or the URI abstractions. Once you’ve resolved the file you’ll need to create a FileStream object. This is the object that does all the work of actual file IO.
If you’re going to be opening a file for asynchronous access, you’ll want to register some event handlers next - before you open the file or start working with its bytes. When you open the file you will call either FileStream.open() or FileStream.openAsync() which are indicative of synchronous and asynchronous file access respectively. You’ll also need to reference which type of access you will be using (i.e. read, write, append, update).
Once you’ve got that setup, you can read and write at your leisure using any of the various methods on the FileStream object. These include coverage for everything from least significant bit (endian), reading single bytes, number values, strings and so on. When you’re done with the file, don’t forget to clean up after yourself and close the file using the FileStream.close() method.
I put together a number of examples that show file access from a variety of use-cases. The source code for all those examples, as well as the AIR file is available for download. I’ve also recorded a narration of my original presentation and slides from the Apollo Camp presentation.
I’ve also put together a Connect recording that walks through what each demo is, how it works, and what it does. The examples start with basic text IO in the form of a minimalist text editor. There’s a simple contact manager application that’s repeated twice in the examples - once using XML as the data store and another using ActionScript object serialization. I’ve also included a very basic hex editor (viewer really) and an Exif data viewer for demonstrations of binary file access.

A bonus example I didn’t get a chance to finish all the way is capturing a PNG from the web cam and saving it to disk. The capture, PNG writing and PNG reading all work, but the UI lacks polish. This example also shows how to use a directory listing, which is how the application knows what PNG files are available. You’re welcome to play with this example, though it has been commented out in the AIR.