by Jeff Swartz

Jeff Swartz

Created

10 October 2011

Requirements
Prerequisite knowledge

General experience of building applications
with Flex Builder or the Flex SDK is
suggested. For more details on getting
started with this Quick Start, refer to
Building the Quick Start sample
applications with Flex
.
Required products

Sample files

User level

Intermediate
 
The directory search sample application, shown in Figure 1, demonstrates the following features of working with files in Adobe AIR:
 
  • Reading files asynchronously so that other ActionScript processes can take place as file data is read
  • Getting the file name extension from file names
  • Using the platform-specific nativePath property of a File object
Figure 1. This sample application enables you to search for specific files.
 
Note: This is a sample application provided, as is, for instructional purposes.
 
This sample application includes the following files in the src directory:
 
  • FileSearch.mxml: The main application file in MXML for Flex; includes the code discussed in this article
  • FileSearch-app.xml: The AIR application descriptor file
  • Sample AIR icon files
Important: The application descriptor file, FileCompressionTool-app.xml, uses the AIR 3.0 namespace. To modify and repackage this application, you need to download and use AIR 3 SDK along with Flash Builder 4.5.
 

 
Understanding the code

Note: This article does not describe all of the Flex components used in the MXML code for the file. For more information, see the ActionScript 3 Reference for the Flash Platform.
 
 
Setting the root directory to search
The init() method sets the text value of the folderPath TextInput component to a pre-defined path (the user's documents directory):
 
folderPath.text=File.documentsDirectory.nativePath;
File.documentsDirectory is a File object pointing to the user's documents directory (such as My Documents on Windows), and the nativePath property is a string value of the platform-specific path to the directory. For example, on Windows, this path could be:
 
C:\Documents and Settings\userName\My Documents
Whereas on Mac OS X, it could be:
 
/Users/userName/Documents
The user can edit this value (in the TextArea component), and when the user clicks the Search button, the search() method checks to see if the path is valid, and displays an error message if it is not:
 
var dir:File = new File(folderPath.text); if (!dir.isDirectory) { Alert.show("Invalid directory path.", "Error"); }
Notice the difference between the nativePath property and the url property of a File, listed here for the same directory File object:
 
trace(directory.nativePath); // C:\Documents and Settings\swartz\My Documents trace(directory.url); // file:///C:/Documents%20and%20Settings/swartz/My%20Documents
 
Searching the directory for matching files
The main search process lists directory contents asynchronously, one at a time. By doing this, other ActionScript-based processes (such as the progress bar animation and result listing) can take place as Apollo gets directory listing information (asynchronously) from the file system.
 
The search() method sets up event listeners for the dirListing event, which is dispatched when the getDirectoryListingAsync() process has completed:
 
dir.addEventListener(FileListEvent.DIRECTORY_LISTING, dirListed); dir.getDirectoryListingAsync();
The dirListed() method processes the list of files in the current directory. This list is represented as the files property of the dirListing event. The method sets a currentNodes variable to this array:
 
currentNodes = event.files;
The dirListed() method iterates through each member of this array, to see if it is a directory. If it is a directory, the object is added to a list of current subdirectories (of the current directory being examined).
 
node = currentNodes[i]; if (node.isDirectory) { currentSubdirectories.push(currentNodes[i]); }
After the iteration is completed, the members of this array are added to a master array of directories to be searched, named directoryStack :
 
for (i = currentSubdirectories.length - 1; i > -1; i--) { directoryStack.push(currentSubdirectories[i]); }
At this point, now that processing of the current directory is complete, the application can call another asynchronous listing of the next directory in the stack (if there is one):
 
var dir:File = directoryStack.pop(); if (dir == null) { progress.visible = false; // There are no further directories to search. The search is completed. } else { dir.addEventListener(FileListEvent.DIRECTORY_LISTING, dirListed); dir.listDirectoryAsync(); }

 
Displaying search results

As the dirListed() method iterates through each member of this array of contents of the current directory, it checks if the name matches the Search pattern, and if so, it creates an object that is added to the ArrayCollection that is a data provider for the resultsGrid DataGrid component:
 
if (node.name.search(pattern) > -1) { var newData:Object = {name:node.name, path:node.nativePath, type:node.extension}; resultData.addItem(newData); }