AIR:Articles:Working with Binary Data

AIR:Articles:Working with Binary Data

From Adobe Labs

By Ben Stucki (http://blog.benstucki.net)

The Adobe Flex SDK introduced developers to ActionScript 3.0 and a totally revamped runtime which gives unprecedented access to byte level information. With the introduction of the Adobe Integrated Runtime (AIR) this access is being extended to the desktop, including the ability to read and write local files. In this article I'm going to introduce you to the basics of binary information, how files are stored, and how to access file data using AIR.

Table of contents[showhide]

Requirements

In order to make the most of this article, you need the following software and files:

Sample files: ben_stucki_sample_code.zip (2.1 MB)

A bit about bytes

There was a day not so long ago when I would wait eagerly for information on the next release of Flash. Would it support new image formats? What about audio effects? If I didn't get it in that version, I had to wait for the next one. Then, when ActionScript 3.0 was released, it introduced a set of classes that solved most of my problems at once. These classes gave Flex developers access to binary data.

All of the files on your computer have only one format in common. They are binary files. In fact everything on your computer is binary, and AIR applications can read binary! This means that even if AIR doesn't natively support a file format you need, it's very likely that you can create the functionality on your own. To get started you'll need to unravel the mysteries of binary data, which starts with bits and bytes.

Today binary, tomorrow the world

A single one or zero is called a bit. It quite literally represents the presence or absence of an electron in the processor. To derive information from ones and zeros we group them into sections of eight, called a byte. This grouping is used universally among all computers and operating systems. Table 1 shows how small numbers are represented using a single byte.

Table 1. Decimal to binary comparison

Decimal formatBinary format
000000000
100000001
200000010
300000011
400000100
500000101
25511111111

Note that when the maximum value is reached for a bit, the bit to the left of it is incremented and the remaining bits to the right are reset to 0. We use the same principle in our numbering system, except that we use 0-9 whereas binary only uses 0-1. When we increment the number 9 we get 10, which is a combination of the digits 1 and 0. Similarly, when we increment 1 in binary we get the digits 1 and 0, which represent the number 2.

A byte holds enough digits to count up to 255, but occasionally people may want to count higher or represent data that's not a number. Fortunately there are standards in place for this sort of thing. To count higher than 255, you simply put more bytes together and follow the same pattern. For instance, the Uint data type is stored using four bytes. The Int data type also uses four bytes, but indicates a positive or negative value using its leftmost bit. For most development it's not as important to understand how bytes represent data on such a low level, but you do want to know the number of bytes used to store your data. Table 2 shows an abbreviated list of common data types along with the number of bytes used to store them.

Table 2. Commonly used data types

Data typeBytes
(Byte)1 byte
Int4 bytes
Uint4 bytes
Number8 bytes
String(1 byte per character)

The Int and Uint data types are represented by four bytes as discussed above. The Number data type is represented by eight bytes. Strings are often represented by one byte per character. To work with this data in AIR applications you'll need to be familiar with the ByteArray class, which is used to work with binary data.

Working with the ByteArray class

A ByteArray is exactly what it sounds like. It's an array of bytes. Each element in the array will hold a byte of data, exactly as described above. It's possible to read and write data one byte at a time, but the ByteArray also includes a number of methods for reading common data types from the array.

When working with binary data, you will almost always be reading data sequentially from beginning to end. For this reason, ByteArrays also have a position property, which represents the current index being read in the array. When a method is called that reads data from a ByteArray, the position property is automatically incremented by the number of bytes read. Remember that not all data is stored using a single byte or even a set amount of bytes. It can vary from data type to data type, so not every method will move the ByteArray's position by the same amount.

The methods provided in the ByteArray class to read and write binary data are defined by the IDataInput and IDataOutput interfaces, respectively. All classes that read and write binary data implement these interfaces. Table 3 shows an abbreviated list of methods defined by the IDataInput interface along with the number of bytes each method will read.

Table 3. Commonly used IDataInput methods

MethodBytes readData returned
readByte()1Int
readInt()4Int
readUnsignedInt()4Uint
readDouble()8Number
readUTFBytes(length:uint)(length)String

It's important to note that because all digital data is binary, there is no way for Flex to validate that the bytes being read were intended to be a specific data type. Any four bytes can be read as an int or as four characters in a String. To know what data to expect, you'll need to reference the specification for the type of data you're reading. In the next section I'll walk you through an example of using Flex to parse a file using AIR.

Reading binary data

Now that you know what binary data is and how it's handled using the ByteArray, you need to know how the basic data types are used to form more complex files. To get started you need to gain access to a file's bytes.

Opening binary files

Opening a file in an AIR application is incredibly easy. Following the sample code provided in ID3Meta1.mxml, create an AIR application with MXML for a Button component and Script section as shown below:

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
   <mx:Script>
      <![CDATA[
         
         import flash.filesystem.FileMode;
         import flash.filesystem.File;
         
         private var file:File = new File();
         
         private function browse():void {
            var fileFilters:Array = new Array();
            fileFilters.push(new FileFilter("MP3 Files", "*.mp3", "MP3"));
            file.addEventListener(Event.SELECT, selectHandler);
            file.browse(fileFilters);
         }
         
         private function selectHandler( event:Event ):void {
            trace("you selected a file");
         }
         
      ]]>
   </mx:Script>
   <mx:Button label="Browse" right="10" bottom="10" click="browse()"/>
</mx:WindowedApplication>

Notice that the click event of the button has been set to call the browse method, which contains AIR-specific code to create a file dialog prompt for MP3 files. When the user has selected a file from the file dialog, the selectHandler method will be called. The selectHandler method can be used to access the contents of the file selected, but first you need to know what the contents are.

What's in a file?

The contents of a file are defined by the specification for that file format. Some file format specifications are kept private by the company that created them, but many are publicly accessible. One such example is ID3 metadata, which is widely used and has a public specification available at http://www.id3.org/id3v2.3.0. ID3 metadata is added to most MP3 files to carry information about the audio such as title, artist, or album name. Here's a look at the makeup of an MP3 file that uses an ID3v2.3 tag:

Image:Ben_stucki_fig01.jpg

The first three bytes of an MP3 file using an ID3 tag are going to be the characters 'I', 'D', and '3', followed by a one byte integer representing the major revision and another one byte integer representing the minor revision. A single byte is then reserved for settings, followed by a custom four byte integer which is used to give the remaining length of the tag. I've provided a function, convertSynchsafe, in the source to read the custom integer. You can use standard methods to read the remaining data as in the example code from ID3Meta2.mxml shown below:

var tagId:String = bytes.readUTFBytes(3); // ID3
 var majorVersion:Number = bytes.readByte(); // 3
 var minorVersion:Number = bytes.readByte(); // 0
 var flags:int = bytes.readByte(); // flags
 var tagSize:uint = convertSynchsafe(bytes.readUnsignedInt()); // size (in bytes)

Next the specification says you're going to encounter a frame. Frames are a very common structure in binary files (other files call them chuncks, blocks, atoms, etc). Each frame in a file will follow the same basic structure, which contains an ID and length. This allows parsers to skip sections of the file it doesn't recognize. Here is how the ID3 specification defines a frame:

Image:Ben_stucki_fig02.jpg

A four character ID is provided to identify the frame, followed by a standard four byte integer. Then two bytes are provided which contain frame settings. Below is a section of sample code from ID3Meta3.mxml which will loop through all ID3 frames and trace the ID.

 while(bytes.position < tagSize) {
    var id:String = bytes.readUTFBytes(4);
    var size:uint = bytes.readUnsignedInt();
    var flags1:int = bytes.readByte();
    var flags2:int = bytes.readByte();
    if(id!="") { trace(id); }
    bytes.position += size;
 }

Now that you can navigate through the structure of the file, I'll show you how to pull out some useful information to display to the user. First, add a text field to the application.

 <mx:TextArea id="metaText" top="5" right="5" bottom="50" left="180" />

Now you can populate it with data from the file. The easiest ID3 frames to read are text frames. The ID3v2.3 specification states that all frames that have an ID beginning with T are text frames and therefore have the same format. After the frame header, they will have one byte that determines the text encoding, followed immediately by the text itself. Text encodings determine how many bytes represent a character as well as how those bytes are mapped to characters.

In more robust applications, you should account for any encoding specified, but for this sample you may assume that the text can be read as UTF-8, which is the most common. You may also assume that the remainder of the frame length is populated with text. Modify the selectedHandler method to populate the TextArea when text frames are found as shown in the example code from ID3Meta4.mxml below:

if(id.charAt(0)=="T") {
    var encodingFlag:int = bytes.readByte();
    var text:String = bytes.readUTFBytes(size-1);
    metaText.text += id + ": " + text + "/r";
} else {
    bytes.position += size;
}

Now you have a desktop application that allows users to select an MP3 file and retrieve information from that file. You're already parsing text frames from ID3 tags, and you know where to find the ID3 specification. Why not retrieve and display the cover art image next?

Where to go from here

In this article I walked you though the basics of binary information, what it's made of, and how it's used to create complex data. I showed you how to open a file using Adobe Integrate Runtime (AIR) and begin reading bytes from it. Then, I gave you a peak at the ID3 specification as an example file format and walked you through converting the specification into ActionScript 3.0 code. Now that you've got the basics covered, you can start adding advanced functionality to your own AIR applications!

About the author

Ben Stucki is a Software Engineer at Atellis, a Washington D.C. based firm that specializes in developing Rich Internet Applications and products. As part of the core development team at Atellis, Ben mixes his knowledge of back-end application development and interactive user interfaces to engineer next generation Flex applications and components. Ben is also an active member of the Flex community, has contributed to published works, and maintains a weblog devoted to Flash and application development at http://blog.benstucki.net/.

 

转载于:https://www.cnblogs.com/duadu/archive/2009/07/12/6335646.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值