Working with files
Back to: Apollo Documentation home page
Using the Apollo file API, you can add basic file interaction capabilities to your applications. For example, you can read and write files, copy and delete files, and so on. Since your applications can access the local file system, you should refer to Understanding Apollo security if you haven't already done so.
Getting file information
The File class includes the following properties that provide information about a file or directory to which a File object points:
- creationDate
- creator
- exists
- isDirectory
- modificationDate
- name
- nativePath
- parent
- size
- type
- url
For details on these properties, see the File class entry in the Apollo ActionScript 3.0 Language Reference.
Copying and moving files
The File class includes two methods for copying files or directories: copyTo() and copyToAsync(). The File class includes two methods for moving files or directories: moveTo() and moveToAsync(). The copyTo() and moveTo() methods work synchronously, and the copyToAsync() and moveToAsync() methods work asynchronously (see Synchronous and asynchronous methods).
To copy or move a file, you set up two File objects. One points to the file to copy or move, and it is the object that calls the copy or move method, the other points to the destination (result) path.
The following copies a test.txt file from the Apollo Test subdirectory of the user's documents directory to a file named copy.txt in the same directory:
ActionScript example:
var original:File = File.documentsDirectory;
original = original.resolve("Apollo Test/test.txt");
var newFile:File = File.documentsDirectory;
newFile = newFile.resolve("Apollo Test/copy.txt");
original.copyTo(newFile, true);
JavaScript example:
var original = runtime.flash.filesystem.File.documentsDirectory;
original = original.resolve("Apollo Test/test.txt");
var newFile:File = runtime.flash.filesystem.File.documentsDirectory;
newFile = newFile.resolve("Apollo Test/copy.txt");
original.copyTo(newFile, true);
Note that in this example, the value of clobber parameter of the copyTo() method (the second parameter) is set to true. By setting this to true, an existing target file is overwritten. This parameter is optional. If you set it to true (the default value), the operation dispatches an IOErrorEvent event if the target file already exists (and the file is not copied).
The Async versions of the copy and move methods work asynchronously. Use the addEventListener() method to monitor completion of the task or error conditions, as in the following code:
ActionScript example:
var original = File.documentsDirectory;
original = original.resolve("Apollo Test/test.txt");
var destination:File = File.documentsDirectory;
destination = destination.resolve("Apollo Test 2/copy.txt");
original.addEventListener(Event.COMPLETE, fileMoveCompleteHandler);
original.addEventListener(IOErrorEvent.IO_ERROR, fileMoveIOErrorEventHandler);
original.moveToAsync(destination);
function fileMoveCompleteHandler(event:Event):void {
trace(event.target); // [object File]
}
function fileMoveIOErrorEventHandler(event:IOErrorEvent):void {
trace("I/O Error.");
}
JavaScript example:
var original = runtime.flash.filesystem.File.documentsDirectory;
original = original.resolve("Apollo Test/test.txt");
var destination = runtime.flash.filesystem.File.documentsDirectory;
destination = destination.resolve("Apollo Test 2/copy.txt");
original.addEventListener(runtime.flash.events.Event.COMPLETE, fileMoveCompleteHandler);
original.addEventListener(runtime.flash.events.IOErrorEvent.IO_ERROR, fileMoveIOErrorEventHandler);
original.moveToAsync(destination);
function fileMoveCompleteHandler(event){
alert(event.target); // [object File]
}
function fileMoveIOErrorEventHandler(event) {
alert("I/O Error.");
}
The File class also includes the File.moveToTrash() and File.moveToTrashAsync() methods, which move a file or directory to the system trash.
Deleting a file
The File class includes a deleteFile() method and a deleteFileAsync() method. These both delete files, the first working synchronously, the second working asynchronously (see Synchronous and asynchronous methods).
For example, the following code synchronously deletes the test.txt file in the user's documents directory:
ActionScript example:
var directory:File = File.documentsDirectory.resolve("test.txt");
directory.deleteFile();
JavaScript example:
var directory = runtime.flash.filesystem.File.documentsDirectory.resolve("test.txt");
directory.deleteFile();
The following code asynchronously deletes the test.txt subdirectory of the user's documents directory:
ActionScript example:
var file:File = File.documentsDirectory.resolve("test.txt");
file.addEventListener(Event.COMPLETE, completeHandler)
file.deleteFileAsync();
function completeHandler(event:Event):void {
trace("Deleted.")
}
JavaScript example:
var file = runtime.flash.filesystem.File.documentsDirectory.resolve("test.txt");
file.addEventListener(runtime.flash.events.Event.COMPLETE, completeHandler)
file.deleteFileAsync();
function completeHandler(event) {
alert("Deleted.")
}
Also included are the moveToTrash() and moveToTrashAsync methods, which you can use to move a file or directory to the System trash. For details, see Moving a file to the trash.
Moving a file to the trash
The File class includes a moveToTrash() method and a moveToTrashAsync() method. These both send a file or directory to the System trash, the first working synchronously, the second working asynchronously (see Synchronous and asynchronous methods).
For example, the following code synchronously moves the test.txt file in the user's documents directory to the System trash:
ActionScript example:
var file:File = File.documentsDirectory.resolve("test.txt");
file.moveToTrash();
JavaScript example:
var file = runtime.flash.filesystem.File.documentsDirectory.resolve("test.txt");
file.moveToTrash();
Creating a temporary file
The File class includes a createTempFile() method, which creates a new file in the temporary directory folder for the System, as in the following example:
ActionScript example:
var temp:File = File.createTempFile();
JavaScript example:
var temp = runtime.flash.filesystem.File.createTempFile();
The createTempFile() method automatically creates a unique temporary file (saving you the work of determining a new unique location).
You may use a temporary file to temporarily store information used in a session of the application. Note that there is also a createTempDirectory() method, for creating a new, unique temporary directory in the System temporary directory.
You may want to delete the temporary file before closing the application, as it is not automatically deleted.
Reading and writing files
The FileStream class lets Apollo applications read and write to the file system. The general process for reading and writing files is the following:
- Initialize a File object that points to the path of the file that you want to work with. This can be a path to a file that does not yet exist (if you will be creating the file).
ActionScript example: var file:File = File.documentsDirectory.resolve("Apollo Test/testFile.txt");
JavaScript example: var file = runtime.flash.filesystem.File.documentsDirectory.resolve("Apollo Test/testFile.txt");
This example uses the File.documentsDirectory property and the resolve() method of a File object to initialize the File object. However, there are many other ways to point a File object to a file. For more information, see Pointing a File object to a file.
- Initialize a FileStream object.
- Call the open() method or the openAsync() method (depending on whether you want to open the file for synchronous operations or for asynchronous operations). Use the File object as the file parameter of the open method. For the fileMode parameter, specify a constant from the FileMode class that specifies the way in which you will use the file.
For example, the following code initializes a FileStream object that will be used to create a file and overwrite any existing data:
ActionScript example: var fileStream:FileStream = new FileStream();fileStream.open(file, FileMode.WRITE);
JavaScript example: var fileStream = new runtime.flash.filesystem.FileStream();fileStream.open(file, runtime.flash.filesystem.FileMode.WRITE);
For more information, see Initializing a FileStream object, and opening and closing files and FileStream open modes.
- If you opened the file asynchronously (using the openAsync()) method, add and set up event listeners for the FileStream object.
These event listener methods will respond to events dispatched by the FileStream object in a variety of situations, such as when data is read in from the file, when I/O errors are encountered, or when the complete amount of data to be written has been written.
For details, see Asynchronous programming and the events generated by a FileStream object opened asynchronously.
- Include code for reading and writing data, as needed.
There are a number of methods of the FileStream class related to reading and writing. (They each begin with "read" or "write".) The method you choose to use to read or write data depends on the format of the data in the target file.
For example, if the data in the target file is UTF-encoded text, you may use the readUTFBytes() and writeUTFBytes() methods. If you want to deal with the data as byte arrays, you may use the readByte(), readBytes(), writeByte(), and writeBytes() methods.
For details, see Data formats, and choosing the read and write methods to use.
- Call the close() method of the FileStream object when you are done working with the file.
This makes the file available to other applications.
For details, see Initializing a FileStream object, and opening and closing files.
The sections that follow provide more details on using the Apollo file APIs to read and write files.
For examples of using FileStream object to read and write files, see the following Quick Start sections:
FileStream open modes
The open() and openAsync() method of a FileStream object each include a fileMode parameter, which defines a number of properties for a file stream, including the following:
- The ability to read from the file
- The ability to write to the file
- Whether data will always be appended past the end of the file (when writing)
- What to do when the file does not exist (and when its parent directories do not exist)
The following table summarizes the various file modes (which you can specify as the fileMode parameter of the open() and openAsync() methods):
| FileMode constant | Description |
|---|---|
| FileMode.READ | Specifies that the file is open for reading only. |
| FileMode.WRITE | Specifies that the file is open for writing. If the file does not exist, it is created when the FileStream object is opened. If the file does exist, any existing data is deleted. |
| FileMode.APPEND | Specifies that the file is open for appending. The file is created if it does not exist. If the file already exists, existing data is not overwritten, and all writing begins at the end of the file. |
| FileMode.UPDATE | Specifies that the file is open for reading and writing. If the file does not exist, it is not created. Specify this mode for random read/write access to the file. You can read from any position in the file, and when writing to the file, only the bytes written overwrite existing bytes (all other bytes remain unchanged). |
Initializing a FileStream object, and opening and closing files
When you open a FileStream object, you make it available to read and write data to a file. You open a FileStream object by passing a File object to the open() or openAsync() method of the FileStream object:
ActionScript example:
var myFile:File = File.documentsDirectory.resolve("Apollo Test/test.txt");
var myFileStream:FileStream = new FileStream();
myFileStream.open(myFile, FileMode.READ);
JavaScript example:
var myFile = runtime.flash.filesystem.File.documentsDirectory.resolve("Apollo Test/test.txt");
var myFileStream = new runtime.flash.filesystem.FileStream();
myFileStream.open(myFile, runtime.flash.filesystem.FileMode.READ);
The fileMode parameter (the second parameter of the open() and openAsync() methods, specifies the mode in which to open the file: for read, write, append, or update. For details, see the previous section, FileStream open modes.
If you use the openAsync() method, to open the file for asynchronous file operations, set up event listeners to handle the asynchronous events:
ActionScript example:
var myFile:File = File.documentsDirectory.resolve("Apollo Test/test.txt");
var myFileStream:FileStream = new FileStream();
myFileStream.addEventListener(Event.COMPLETE, completeHandler);
myFileStream.addEventListener(ProgressEvent.PROGRESS, progressHandler);
myFileStream.addEventListener(IOErrorEvent.IOError, errorHandler);
myFileStream.open(myFile, FileMode.READ);
function completeHandler(event:Event):void {
// ...
}
function progressHandler(event:ProgressEvent):void {
// ...
}
function errorHandler(event:IOErrorEvent):void {
// ...
}
JavaScript example:
var myFile = runtime.flash.filesystem.File.documentsDirectory.resolve("Apollo Test/test.txt");
var myFileStream = new runtime.flash.filesystem.FileStream();
myFileStream.addEventListener(runtime.flash.events.Event.COMPLETE, completeHandler);
myFileStream.addEventListener(runtime.flash.events.ProgressEvent.PROGRESS, progressHandler);
myFileStream.addEventListener(runtime.flash.events.IOErrorEvent.IOError, errorHandler);
myFileStream.open(myFile, runtime.flash.filesystem.FileMode.READ);
function completeHandler(event) {
// ...
}
function progressHandler(event) {
// ...
}
function errorHandler(event) {
// ...
}
The file is opened for synchronous or asynchronous operations, depending upon whether you use the open() or openAsync() method. For details, see Synchronous and asynchronous methods.
If you set the fileMode parameter to FileMode.READ or FileMode.UPDATE in the open method of the FileStream object, data is read into the read buffer as soon as you open the FileStream object. For details, see The read buffer and the bytesAvailable property of a FileStream object.
You can call the close() method of a FileStream object to close the associated file, making it available for use by other applications.
The position property of a FileStream object
The position property of a FileStream object determines where data will be read or written on the next read or write method.
Prior to a read or write operation, set the position property to any valid position in the file.
For example, the following code writes the string "hello" (in UTF encoding) at position 8 in the file:
ActionScript example:
var myFile:File = File.documentsDirectory.resolve("Apollo Test/test.txt");
var myFileStream:FileStream = new FileStream();
myFileStream.open(myFile, FileMode.UPDATE);
myFileStream.position = 8;
myFileStream.writeUTFBytes("hello");
JavaScript example:
var myFile = runtime.flash.filesystem.File.documentsDirectory.resolve("Apollo Test/test.txt");
var myFileStream = new runtime.flash.filesystem.FileStream();
myFileStream.open(myFile, runtime.flash.filesystem.FileMode.UPDATE);
myFileStream.position = 8;
myFileStream.writeUTFBytes("hello");
When you first open a FileStream object, the position property is set to 0.
Prior to a read operation, the value of position must be at least 0 and less than the number of bytes in the file (which are existing positions in the file).
The value of the position property is modified only in the following conditions:
- When you explicitly set the position property.
- When you call a read method.
- When you call a write method.
When you call a read or write method of a FileStream object, the position property is immediately incremented by the number of bytes that you will read or write. Depending on the read method you use, this will mean that the position property is either incremented by the number of bytes you specify to read, or by the number of bytes available. When you call a read or write method subsequently, it will read or write starting at the new position.
ActionScript example:
var myFile:File = File.documentsDirectory.resolve("Apollo Test/test.txt");
var myFileStream:FileStream = new FileStream();
myFileStream.open(myFile, FileMode.UPDATE);
myFileStream.position = 4000;
(myFileStream.position); // 4000
myFileStream.writeBytes(myByteArray, 0, 200);
trace(myFileStream.position); // 4200
JavaScript example:
var myFile = runtime.flash.filesystem.File.documentsDirectory.resolve("Apollo Test/test.txt");
var myFileStream = new runtime.flash.filesystem.FileStream();
myFileStream.open(myFile, runtime.flash.filesystem.FileMode.UPDATE);
myFileStream.position = 4000;
alert(myFileStream.position); // 4000
myFileStream.writeBytes(myByteArray, 0, 200);
alert(myFileStream.position); // 4200
There is, however, one exception: for a FileStream opened in append mode, the position property is not changed after a call to a write method. (In append mode, data is always written to the end of the file, independent of the value of the position property.)
Note that for a file opened for asynchronous operations, the write operation does not complete before the next line of code is executed. However, you can call multiple asynchronous methods sequentially, and the runtime will execute them in order:
ActionScript example:
var myFile:File = File.documentsDirectory.resolve("Apollo Test/test.txt");
var myFileStream:FileStream = new FileStream();
myFileStream.openAsync(myFile, FileMode.WRITE);
myFileStream.writeUTFBytes("hello");
myFileStream.writeUTFBytes("world");
myFileStream.addEventListener(Event.CLOSE, closeHandler);
myFileStream.close()
trace("started.");
closeHandler(event:Event):void
{
trace("finished.");
}
JavaScript example:
var myFile = runtime.flash.filesystem.File.documentsDirectory.resolve("Apollo Test/test.txt");
var myFileStream = new runtime.flash.filesystem.FileStream();
myFileStream.openAsync(myFile, runtime.flash.filesystem.FileMode.WRITE);
myFileStream.writeUTFBytes("hello");
myFileStream.writeUTFBytes("world");
myFileStream.addEventListener(runtime.flash.events.Event.CLOSE, closeHandler);
myFileStream.close()
runtime.trace("started.");
closeHandler(event:Event):void
{
trace("finished.");
}
The trace output for this code is the following:
started. finished.
You can specify the position value immediately after you call a read or write method (or at any time), and the next read or write operation will take place starting at that position. For example, note that the following code sets the position property right after a call to the writeBytes() operation, and the position is set to that value (300) even after the write operation completes:
ActionScript example:
var myFile:File = File.documentsDirectory.resolve("Apollo Test/test.txt");
var myFileStream:FileStream = new FileStream();
myFileStream.openAsync(myFile, FileMode.UPDATE);
myFileStream.position = 4000;
trace(myFileStream.position); // 4000
myFileStream.writeBytes(myByteArray, 0, 200);
myFileStream.position = 300;
trace(myFileStream.position); // 300
JavaScript example:
var myFile = runtime.flash.filesystem.File.documentsDirectory.resolve("Apollo Test/test.txt");
var myFileStream = new runtime.flash.filesystem.FileStream();
myFileStream.openAsync(myFile, runtime.flash.filesystem.FileMode.UPDATE);
myFileStream.position = 4000;
runtime.trace(myFileStream.position); // 4000
myFileStream.writeBytes(myByteArray, 0, 200);
myFileStream.position = 300;
runtime.trace(myFileStream.position); // 300
The read buffer and the bytesAvailable property of a FileStream object
As a FileStream object with read capabilities (one in which the fileMode parameter of the open() or openAsync() method was set to READ or UPDATE), it stores the data in an internal buffer. The FileStream object begins reading data into the buffer as soon as you open the file (by calling the open() or openAsync() method of the FileStream object).
For a file opened for synchronous operations (using the open() method), you can always set the position pointer to any valid position (within the bounds of the file) and begin reading any amount of data (within the bounds of the file), as shown in the following code (which assumes that the file contains at least 100 bytes):
ActionScript example:
var myFile:File = File.documentsDirectory.resolve("Apollo Test/test.txt");
var myFileStream:FileStream = new FileStream();
myFileStream.open(myFile, FileMode.READ);
myFileStream.position = 10;
myFileStream.readBytes(myByteArray, 0, 20);
myFileStream.position = 89;
myFileStream.readBytes(myByteArray, 0, 10);
JavaScript example:
var myFile = runtime.flash.filesystem.File.documentsDirectory.resolve("Apollo Test/test.txt");
var myFileStream = new runtime.flash.filesystem.FileStream();
myFileStream.open(myFile, runtime.flash.filesystem.FileMode.READ);
myFileStream.position = 10;
myFileStream.readBytes(myByteArray, 0, 20);
myFileStream.position = 89;
myFileStream.readBytes(myByteArray, 0, 10);
For files opened for synchronous operations, the bytesAvailable property is always set to represent the number of bytes from the position property to the end of the file (all bytes in the file are always available for reading).
For files opened for asynchronous operations, you need to ensure that the read buffer has consumed enough data prior to calling a read method. For a file opened asynchronously, as the read operation progresses, the data from the file, starting at the position specified when the read operation started, is added to the buffer, and the bytesAvailable property increments with each byte read. The bytesAvailable property indicates the number of bytes available starting with the byte at the position specified by the position property to the end of the buffer. Periodically, the FileStream object sends a progress event.
For a file opened asynchronously, as data is read, the FileStream object periodically dispatches the progress event. For example, the following code reads data into a ByteArray object, bytes, as it is read into the buffer:
ActionScript example:
var bytes:ByteArray = new ByteArray();
var myFile:File = File.documentsDirectory.resolve("Apollo Test/test.txt");
var myFileStream:FileStream = new FileStream();
myFileStream.addEventListener(ProgressEvent.PROGRESS, progressHandler);
myFileStream.openAsync(myFile, FileMode.READ);
function progressHandler(event:ProgressEvent):void
{
myFileStream.readBytes(bytes, myFileStream.position, myFileStream.bytesAvailable);
}
JavaScript example:
var bytes = new runtime.flash.utils.ByteArray();
var myFile = new runtime.flash.filesystem.File.documentsDirectory.resolve("Apollo Test/test.txt");
var myFileStream = new runtime.flash.filesystem.FileStream();
myFileStream.addEventListener(runtime.flash.events.ProgressEvent.PROGRESS, progressHandler);
myFileStream.openAsync(myFile, runtime.flash.filesystem.FileMode.READ);
function progressHandler(event)
{
myFileStream.readBytes(bytes, myFileStream.position, myFileStream.bytesAvailable);
}
For a file opened asynchronously, only the data in the read buffer can be read. Furthermore, as you read the data, it is removed from the read buffer. For read operations, you will need to ensure that the data exists in the read buffer prior to calling the read operation. You may do this by setting up a progress handler. For example, the following code reads 8000 bytes of data starting from position 4000 in the file:
ActionScript example:
var myFile:File = File.documentsDirectory.resolve("Apollo Test/test.txt");
var myFileStream:FileStream = new FileStream();
myFileStream.addEventListener(ProgressEvent.PROGRESS, progressHandler);
myFileStream.addEventListener(Event.COMPLETE, completed);
myFileStream.openAsync(myFile, FileMode.READ);
myFileStream.position = 4000;
var str:String = "";
function progressHandler(event:Event):void
{
if (myFileStream.bytesAvailable > 8000 )
{
str += myFileStream.readMultiByte(8000, "iso-8859-1");
}
}
JavaScript example:
var myFile = runtime.flash.filesystem.File.documentsDirectory.resolve("Apollo Test/test.txt");
var myFileStream = new runtime.flash.filesystem.FileStream();
myFileStream.addEventListener(runtime.flash.events.ProgressEvent.PROGRESS, progressHandler);
myFileStream.addEventListener(runtime.flash.events.Event.COMPLETE, completed);
myFileStream.openAsync(myFile, runtime.flash.filesystem.FileMode.READ);
myFileStream.position = 4000;
var str = "";
function progressHandler(event)
{
if (myFileStream.bytesAvailable > 8000 )
{
str += myFileStream.readMultiByte(8000, "iso-8859-1");
}
}During a write operation, the FileStream object does not read data into the read buffer. When a write operation completes (all data in the write buffer is written to the file), the FileStream object starts a new read buffer (assuming that the associated FileStream object was opened with read capabilities), and starts reading data into the read buffer, starting from the position specified by the position property. The position property may be the position of the last byte written, or it may be a different position, if the user specifies a different value for the position object during the course of the write operation.
Asynchronous programming and the events generated by a FileStream object opened asynchronously
When a file is opened asynchronously (using the openAsync() method), reading and writing files are done asynchronously. As data is read into the read buffer and as output data is being written, other ActionScript code can execute.
This means that you will need to register for events generated by the FileStream object opened asynchronously.
By registering for the progress event, you can ensure that some data has been read into the read buffer when you attempt to read it, as in the following code:
ActionScript example:
var myFile:File = File.documentsDirectory.resolve("Apollo Test/test.txt");
var myFileStream:FileStream = new FileStream();
myFileStream.addEventListener(ProgressEvent.PROGRESS, progressHandler);
myFileStream.openAsync(myFile, FileMode.READ);
var str:String = "";
function progressHandler(event:ProgressEvent):void
{
str += myFileStream.readMultiByte(myFileStream.bytesAvailable, "iso-8859-1");
}
JavaScript example:
var myFile = runtime.flash.filesystem.File.documentsDirectory.resolve("Apollo Test/test.txt");
var myFileStream = new runtime.flash.filesystem.FileStream();
myFileStream.addEventListener(runtime.flash.events.ProgressEvent.PROGRESS, progressHandler);
myFileStream.openAsync(myFile, runtime.flash.filesystem.FileMode.READ);
var str = "";
function progressHandler(event)
{
str += myFileStream.readMultiByte(myFileStream.bytesAvailable, "iso-8859-1");
}
You can read the entire data by registering for the complete event, as in the following code:
ActionScript example:
var myFile:File = File.documentsDirectory.resolve("Apollo Test/test.txt");
var myFileStream:FileStream = new FileStream();
myFileStream.addEventListener(Event.COMPLETE, completed);
myFileStream.openAsync(myFile, FileMode.READ);
var str:String = "";
function completeHandler(event:Event):void
{
str = myFileStream.readMultiByte(myFileStream.bytesAvailable, "iso-8859-1");
}
JavaScript example:
var myFile = runtime.flash.filesystem.File.documentsDirectory.resolve("Apollo Test/test.txt");
var myFileStream = new runtime.flash.filesystem.FileStream();
myFileStream.addEventListener(runtime.flash.events.Event.COMPLETE, completed);
myFileStream.openAsync(myFile, runtime.flash.filesystem.FileMode.READ);
var str = "";
function completeHandler(event)
{
str = myFileStream.readMultiByte(myFileStream.bytesAvailable, "iso-8859-1");
}
As data is written to a file, the FileStream object periodically dispatched an OutputProgressEvent object. An OutputProgressEvent object includes a bytesPending property that is set to the number of bytes remaining to be written.
Data formats, and choosing the read and write methods to use
Every file is a set of bytes on a disk. In ActionScript, the data from a file can always be represented as a ByteArray. For example, the following code reads the data from a file into a ByteArray object named bytes:
ActionScript example:
var myFile:File = File.documentsDirectory.resolve("Apollo Test/test.txt");
var myFileStream:FileStream = new FileStream();
myFileStream.addEventListener(Event.COMPLETE, completed);
myFileStream.openAsync(myFile, FileMode.READ);
function completeHandler(event:Event):void
{
myFileStream.readBytes(bytes, 0, myFileStream.bytesAvailable);
}
JavaScript example:
var myFile = runtime.flash.filesystem.File.documentsDirectory.resolve("Apollo Test/test.txt");
var myFileStream = new runtime.flash.filesystem.FileStream();
myFileStream.addEventListener(runtime.flash.events.Event.COMPLETE, completed);
myFileStream.openAsync(myFile, runtime.flash.filesystem.FileMode.READ);
function completeHandler(event)
{
myFileStream.readBytes(bytes, 0, myFileStream.bytesAvailable);
}
Similarly, the following code writes data from a ByteArray named bytes to a file:
ActionScript example:
var myFile:File = File.documentsDirectory.resolve("Apollo Test/test.txt");
var myFileStream:FileStream = new FileStream();
myFileStream.open(myFile, FileMode.WRITE);
myFileStream.writeBytes(bytes, 0, bytes.length);
JavaScript example:
var myFile = runtime.flash.filesystem.File.documentsDirectory.resolve("Apollo Test/test.txt");
var myFileStream = new runtime.flash.filesystem.FileStream();
myFileStream.open(myFile, runtime.flash.filesystem.FileMode.WRITE);
myFileStream.writeBytes(bytes, 0, bytes.length);
However, often you do not want to store the data in an ActionScript ByteArray object. And often the data file will be in a specified file format.
For example, the data in the file may be in a text file format, and you may want to represent such data in a String object.
For this reason, the FileStream class includes read and write methods for reading and writing data to and from types other than ByteArray objects. For example, the readMultiByte() method lets you read data from a file and store it to a string, as in the following code:
ActionScript example:
var myFile:File = File.documentsDirectory.resolve("Apollo Test/test.txt");
var myFileStream:FileStream = new FileStream();
myFileStream.addEventListener(Event.COMPLETE, completed);
myFileStream.openAsync(myFile, FileMode.READ);
var str:String = "";
function completeHandler(event:Event):void
{
str = myFileStream.readMultiByte(myFileStream.bytesAvailable, "iso-8859-1");
}
JavaScript example:
var myFile = runtime.flash.filesystem.File.documentsDirectory.resolve("Apollo Test/test.txt");
var myFileStream = new runtime.flash.filesystem.FileStream();
myFileStream.addEventListener(runtime.flash.events.Event.COMPLETE, completed);
myFileStream.openAsync(myFile, runtime.flash.filesystem.FileMode.READ);
var str = "";
function completeHandler(event)
{
str = myFileStream.readMultiByte(myFileStream.bytesAvailable, "iso-8859-1");
}
Note that the second parameter of the readMultiByte() method specifies the text format that ActionScript uses to interpret the data ("iso-8859-1" in the example). ActionScript supports a number of common character set encodings, and these are listed in the ActionScript Language Reference (see Supported character sets).
The FileStream class also includes the readUTFBytes() method, which reads data from the read buffer into a string using the UTF-8 character set. Since characters in the the UTF-8 character set is are of a variable length, you should not try to use readUTFBytes() in a method that responds to the progress event, since the data at the end of the read buffer may represent an incomplete character. (This is also true when using the readMultiByte() method with a variable-length character encoding.) For this reason, you should read the entire data when the FileStream object dispatches the complete event.
There are also similar write methods, writeMultiByte() and writeUTFBytes(), for working with String objects and text files.
Note that the readUTF() and the writeUTF() methods (not to be confused with readUTFBytes() and writeUTFBytes()) also read and write the text data to a file, but they assume that the text data is preceded by data specifying the length of the text data, which is not a common practice in standard text files.
Some UTF-encoded text files begin with a "UTF-BOM" (byte order mark) character that defines the endianess as well as the encoding format (such as UTF-16 or UTF-32).
For an example of reading and writing to a text file, see Example: reading an XML file into an XML object (and writing an XML object to a file).
The readObject() and writeObject() are convenient ways to store and retrieve data for complex ActionScript objects. The data is encoded in AMF (ActionScript Message Format). This format is proprietary to ActionScript. Applications other than Apollo, Flash Player, Flash Media Server, and Flex Data Services do not have built-in APIs for working with data in this format.
There are a number of other read and write methods (such as readDouble() and writeDouble()). However, if you use these, make sure that the file format matches the formats of the data defined by these methods.
File formats are often more complex than simple text formats. For example, an MP3 file includes compressed data that can only be interpreted with the decompression and decoding algorithms specific to MP3 files. MP3 files also may include ID3 tags that contain metatag information about the file (such as the title and artist for a song). There are multiple versions of the ID3 format, but the simplest (ID3 version 1) is discussed in the Example: Working with ID3 version 1.0 data section.
Other files formats (for images, databases, application documents, etc.) have quite different structures, and to work with their data in ActionScript, you need to understand how the data is structured.
Example: reading an XML file into an XML object (and writing an XML object to a file)
This section shows how to read and write to a text file that contains XML data.
Reading from the file is easy. Simply initialize the File and FileStream objects, and set up an event listener for the complete event:
ActionScript example:
var file:File = File.documentsDirectory.resolve("Apollo Test/preferences.xml");
var fileStream:FileStream = new FileStream();
fileStream.open(file, FileMode.READ);
var prefsXML:XML = XML(fileStream.readUTFBytes(fileStream.bytesAvailable));
fileStream.close();
JavaScript example:
var file = runtime.flash.filesystem.File.documentsDirectory.resolve("Apollo Test/preferences.xml");
var fileStream = new runtime.flash.filesystem.FileStream();
fileStream.open(file, runtime.flash.filesystem.FileMode.READ);
var prefsXML = fileStream.readUTFBytes(fileStream.bytesAvailable);
fileStream.close();
Similarly, writing the data to the file is as easy as setting up an appropriate File and FileStream objects, and then calling a write method of the FileStream object, passing the string version of the XML data to the write method as in the following code:
ActionScript example:
var file:File = File.documentsDirectory.resolve("Apollo Test/preferences.xml");
fileStream = new FileStream();
fileStream.open(file, FileMode.WRITE);
var outputString:String = '<?xml version="1.0" encoding="utf-8"?>\n';
outputString += prefsXML.toXMLString();
fileStream.writeUTFBytes(outputString);
fileStream.close();
JavaScript example:
var file = runtime.flash.filesystem.File.documentsDirectory.resolve("Apollo Test/preferences.xml");
fileStream = new runtime.flash.filesystem.FileStream();
fileStream.open(file, runtime.flash.filesystem.FileMode.WRITE);
var outputString = '<?xml version="1.0" encoding="utf-8"?>\n';
outputString += prefsXML
fileStream.writeUTFBytes(outputString);
fileStream.close();
Note that these examples use the readUTFBytes() and writeUTFBytes() methods, because they assume that the files are in UTF-8 format. If this is not the case, you may need to use a different method (see Data formats, and choosing the read and write methods to use).
The previous examples use FileStream objects opened for synchronous operation. You can also open files for asynchronous operations (which rely on event listener functions to respond to events). For example, the following code shows how to read an XML file asynchronously:
ActionScript example:
var file:File = File.documentsDirectory.resolve("Apollo Test/preferences.xml");
var fileStream:FileStream = new FileStream();
fileStream.addEventListener(Event.COMPLETE, processXMLData);
fileStream.open(file, FileMode.READ);
var prefsXML:XML;
function processXMLData(event:Event):void
{
prefsXML = XML(fileStream.readUTFBytes(fileStream.bytesAvailable));
fileStream.close();
}
JavaScript example:
var file = runtime.flash.filesystem.File.documentsDirectory.resolve("Apollo Test/preferences.xml");
var fileStream= new runtime.flash.filesystem.FileStream();
fileStream.addEventListener(runtime.flash.events.Event.COMPLETE, processXMLData);
fileStream.open(file, runtime.flash.filesystem.FileMode.READ);
var prefsXML;
function processXMLData(event)
{
prefsXML = fileStream.readUTFBytes(fileStream.bytesAvailable);
fileStream.close();
}
The processXMLData() method is invoked when the entire file is read into the read buffer (when the FileStream object dispatches the complete event). It calls the readUTFBytes() method to get a string version of the read data, and it creates an XML object, prefsXML, based on that string.
To see a sample application that shows these capabilities, see Reading and writing from an XML preferences file.
Example: reading and writing ID3 V1 data (random access)
MP3 files can include ID3 tags, which are sections at the beginning or end of the file that contain metadata identifying the recording. The ID3 tag format itself has gone through a number of formats. This section describes how to read and write from an MP3 file that contains the simplest ID3 format: ID3 version 1.0. This example will not be reading and writing to the file sequentially from start to finish, and this is known as random access to file data.
An MP3 file that contains an ID3 version 1 tag includes the ID3 data at the end of the file, in the final 128 bytes.
When accessing a file for random read/write access, it is important to specify FileMode.UPDATE as the fileMode parameter for the open() or openAsync() method:
ActionScript example:
var file:File = File.documentsDirectory.resolve("My Music/Sample ID3 v1.mp3");
var fileStr:FileStream = new FileStream();
fileStr.open(file, FileMode.UPDATE);
JavaScript example:
var file = runtime.flash.filesystem.File.documentsDirectory.resolve("My Music/Sample ID3 v1.mp3");
var fileStr = new runtime.flash.filesystem.FileStream();
fileStr.open(file, runtime.flash.filesystem.FileMode.UPDATE);
This lets you both read and write to the file.
Upon opening the file, you can set the position pointer to the position 128 bytes before the end of the file,
fileStr.position = file.size - 128;
We set the position to this location in the file because the ID3 v1.0 format specifies that the ID3 tag data is stored in the last 128 bytes of the file. The specification also says the following:
- The first 3 bytes of the tag contain the string "TAG".
- The next 30 characters contain the name of the title for the MP3 track, as a string.
- The next 30 characters contain the name of the artist, as a string.
- The next 30 characters contain the name of the album, as a string.
- The next 4 characters contain the name of the year, as a string.
- The next 30 characters contain the comment, as a string.
- The next byte contains a code indicating the track's genre.
- All text data is in "iso-8859-1" format.
The id3TagRead() method checks the data after it is read in (upon the complete event):
ActionScript example:
function id3TagRead():void
{
if (fileStr.readMultiByte(3, "iso-8859-1").match(/tag/i))
{
var id3Title:String = fileStr.readMultiByte(30, "iso-8859-1");
var id3Artist:String = fileStr.readMultiByte(30, "iso-8859-1");
var id3Album:String = fileStr.readMultiByte(30, "iso-8859-1");
var id3Year:String = fileStr.readMultiByte(4, "iso-8859-1");
var id3Comment:String = fileStr.readMultiByte(30, "iso-8859-1");
var id3GenreCode:String = fileStr.readByte().toString(10);
}
}
JavaScript example:
function id3TagRead()
{
if (fileStr.readMultiByte(3, "iso-8859-1").match(/tag/i))
{
var id3Title = fileStr.readMultiByte(30, "iso-8859-1");
var id3Artist = fileStr.readMultiByte(30, "iso-8859-1");
var id3Album = fileStr.readMultiByte(30, "iso-8859-1");
var id3Year = fileStr.readMultiByte(4, "iso-8859-1");
var id3Comment = fileStr.readMultiByte(30, "iso-8859-1");
var id3GenreCode = fileStr.readByte().toString(10);
}
}
You can also perform a random-access write to the file. For example, you could parse the id3Title variable to ensure that it is correctly capitalized (using methods of the String class), and then write a modified string, called newTitle, to the file, as in the following:
fileStr.position = file.length - 125; // 128 - 3 fileStr.writeMultiByte(newTitle, "iso-8859-1");
To conform with the ID3 version 1 standard, the length of the newTitle string should be 30 characters, padded at the end with the character with the code 0 (String.fromCharCode(0)).
Back to: Apollo Documentation home page