Reading iCalendar Files with Flash Player 10
There are many compelling features in Flash Player 10, but if you are a nut about data (like me), then local file IO is probably the one that gets your attention. It turns out that using this new feature couldn’t be easier. There’s a couple new methods on the FileReference class and you are off to the races. I wanted to test this functionality out myself, so I built a little application to read iCalendar files.
I want to be clear that this example is not intended to be a practical implementation of parsing iCalendar files. While I reviewed the RFC 2445 standard, I only grabbed the few pieces I needed for events and this specific display. I also tested only against a specific set of sample data. The real value of this example is in the specifics around file access.
The first thing you need to know about local file IO is that any access to the system must be driven by a user click interaction. You are not free to go about opening files at random, or without user permission. You can also only perform one local access per click and cannot chain the system access. For example, you can’t save some data, and then immediately open some other file without first getting user another click event from the user.
The next thing to know about local file IO is that the methods are designed to work with a ByteArray object. This is pretty clever as it gives you the flexibility to read and write any file type whether it be text, or something more complicated like an image file. RFC 2445 files are text-based and easily human readable. You can download the test file I used, my actual schedule for the week of Nov 3, 2008, or create your own, but for reference, here’s some sample data.
BEGIN:VCALENDAR ... BEGIN:VEVENT SEQUENCE:2 TRANSP:OPAQUE UID:61BC7865-E5CF-4C7A-89A7-45B91592143B DTSTART;TZID=America/Denver:20081103T130000 DTSTAMP:20081102T202730Z SUMMARY:DEN to LGA CREATED:20081102T202722Z DTEND;TZID=America/Denver:20081103T170000 END:VEVENT ... END:VCALENDAR
Now onto the actual implementation details. You will first need to provide a means for the user to indicate that they want to open a local file. In my application, I use the “+” icon in the upper right hand corner of the application. It’s just a MovieClip instance, and I’ve registered a listener for the MouseEvent.CLICK event. When that listener gets fired, we can prompt the user to select a local file using the FileReference.browse() method, but before we got hat far, we have some other work to do first.
All of these operations happen asynchronously. When the user select a file from the browse dialog, an Event.SELECT event will be fired. That lets us know where we can read the local data. Reading the data though, also happens asynchronously, so we’ll need to also register for the Event.COMPLETE event, which will get fired with the local file has been loaded into a ByteArray for further processing. You’ll find that ByteArray object on the FileReference.data property once local access has finished.
public var ical:FileReference = null; public function doAdded( event:Event ):void { ical = new FileReference(); ical.addEventListener( Event.SELECT, doSelect ); ical.addEventListener( Event.COMPLETE, doComplete ); } public function doSelect( event:Event ):void { ical.load(); } public function doComplete( event:Event ):void { var lines:Array = null; var file:String = null; file = ical.data.readMultiByte( ical.data.length, US_ASCII ); lines = file.split( CR_LF ); // ... }
The ByteArray class has a ByteArray.readMultiByte() method on it for reading strings. You might go about using this method in any number of manner, but in this case, I just read in the all available data in the ByteArray instance as a giant string. From there I can use the string methods to parse the details. The RFC 2445 standard uses a carriage return and line feed marker to indicate a new line, which I use to split the string up initially. Then I run through the lines and parse all the relevant data (again using more string manipulation).
The great thing about using ByteArray by default is that it allows you to work with both text files and binary files. For example, there’s no reason that an application couldn’t read or write an image file. Other file types such as PDF or SWF also seem as though they’d be particularly compelling. Or, if you just want to write out some text, you can do that too. It’s very flexible for your specific situation.
Though I didn’t use it in this example, the FileReference.save() method behaves a little differently. Rather than have your user select the file first, you actually need to build the ByteArray object you intend to write to the local system up front. That ByteArray instance will be passed to the FileReference.save() method. From there the user will select where they want to put the file. As soon as they’ve selected a destination, that ByteArray data will be written instantly.
There’s clearly a vast amount of potential with this feature. Image simply not having to bounce simple data off a server anymore whenever you want to save a file locally? The shortcoming for now being that there are few libraries in ActionScript for the countless file types that are in existence. Perhaps now that this feature is available, we’ll see more developers create such libraries. In the meantime, you can download the source for my example. If you expand upon it, and create a full implementation for iCalendar files, please drop me a comment and let me know.
November 10th, 2008 at 5:47 am
Hi Kevin,
Thanks for the example, parsing of ascii files was just what i was looking for.
Do you know if i can also do this (parsing of ascii files) with the ByteArray class in Flash 9 player? Or am i bound to FP10?
Btw the example swf does show up , allows you to select the file and then does notting. I have FP10 r12.
Thanks,
Sidney
November 12th, 2008 at 6:29 pm
Sidney,
Flash Player 10 introduced load/save of local files. While you could browse for files and upload/download them with Flash Player 9, Flash Player 10 adds the load/save functionality.
If you’re using Flash Pro CS3, then you’re probably creating FP9 content. Flash Pro CS4 can publish to FP10.
Does that help?
Kevin
December 17th, 2008 at 2:11 pm
Kevin, as always a you provide us with a sweet example to play with.
I assume the calendar app on the Mac exports ical files - for the rest of us there’s outlook - which reads but lacks export support…. Sourceforge to the rescue… with a open spource outlook export macro.
http://outlook2ical.sourceforge.net/
Enjoy.
Dan
May 15th, 2009 at 4:35 pm
The example does everything I need. However, I can’t seem to cast it as XML and reference the members. How do I go about doing that.
I was trying the following:
file = xml_file.data.readMultiByte( xml_file.data.length, US_ASCII );
mxXML:XML = file as XML;
Any Ideas