September 29, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

How Palm OS Expands Your Applications: Files and Folders

  • June 8, 2005
  • By Alex Gusev
  • Send Email »
  • More Articles »

In my previous article, "How Palm OS Expands Your Applications: Volumes," you learned how to manipulate volumes using VFS Manager. Now, it is time to move on and study Folders and Files. For those of you who are familiar with Windows or Unix programming, these topics will acquaint you with the same philosophy. The next sections will guide you through various operations you can handle over Folders and Files using Virtual File System Manager.

Open, Close, and Enumerate Folders and Files

Prior to making any step forward, I should discuss how VFS Manager addresses folders anf files on some mounted volume. Similar to Windows CE, VFS Manager has no concept of a "current directory;" hence, all paths are absolute within a given volume. You can't use relative paths. The folder separator is a slash character ("/"), and volume's root is addressed as "/".

VFS Manager supports all standard operations on folders and files. Like in many other systems, you may enumerate, create, detete, and rename folders or files, and get or set their attributes and times. Actually, files and folders are handled in a very similar way.

Your starting point will be a folder contents enumeration sample. To proceed with your folders or files, you first need to open them. VFSFileOpen's definition looks pretty simple:

Err VFSFileOpen (UInt16 volRefNum, const Char *pathNameP,
                 UInt16 openMode, FileRef *fileRefP)

You're providing a path and desired mode and getting back a reference to open file/folder. This reference will be used later with all possible operations your applicaiton will carry out upon this file/folder. You can control how the file or folder will be opened via the openMode parameter, which allows you to create files in case they don't exist.

After you've opened some folder, an enumeration is a simple thing. Just take a look at the following sample to admit it:

FileInfoType FileInfo;
FileRef rDir;
UInt32 nDirIterator = vfsIteratorStart;
Char szFileName[256];

// volRefNum is obtained earlier
Err err = VFSFileOpen(volRefNum, "/", vfsModeRead, &rDir);
if(err == errNone)
{
   FileInfo.nameP = szFilename;
   FileInfo.nameBufLen = sizeof(szFilename);
   while (nDirIterator != vfsIteratorStop)
   {
      err = VFSDirEntryEnumerate(rDir, &nDirIterator, &FileInfo);
      if (err == errNone)
      {
         HostTraceOutputTL(appErrorClass,"Found <%s>",szFileName);
      }
      else
      {
         // handle an error
      }
   }
}
else
{
   // handle directory open error here
}

As you see, all the process is not recursive. You sill need to open a folder before you can enumerate it. At this time, please note that you get the detected file's attributes in the FileInfo.attributes member, so you'll easily be able to determine that this particular file is actually a folder and proceed with it as needed.

When you no longer need a particular file or folder resource, you should close it by calling the following:

Err VFSFileClose (FileRef fileRef)

Common Operations

VFS Manager supports a standard set of common file operations. They are listed below, grouped by operation:

Err VFSDirCreate(UInt16 volRefNum,  const Char *dirNameP)
Err VFSFileCreate(UInt16 volRefNum, const Char *pathNameP)
Err VFSFileDelete(UInt16 volRefNum, const Char *pathNameP)
Err VFSFileRename(UInt16 volRefNum, const Char *pathNameP,
                  const Char *newNameP)

Err VFSFileSize(FileRef fileRef, UInt32 *fileSizeP)
Err VFSFileResize(FileRef fileRef, UInt32 newSize)

Err VFSFileGetAttributes(FileRef fileRef, UInt32 *attributesP)
Err VFSFileSetAttributes(FileRef fileRef, UInt32 attributes)

Err VFSFileGetDate(FileRef fileRef, UInt16 whichDate, UInt32 *dateP)
Err VFSFileSetDate(FileRef fileRef, UInt16 whichDate, UInt32 date)

Err VFSGetDefaultDirectory(UInt16 volRefNum,
                           const Char *fileTypeStr,
                           Char *pathStr, UInt16 *bufLenP)
Err VFSRegisterDefaultDirectory(const Char *fileTypeStr,
                                UInt32 mediaType,
                                const Char *pathStr)
Err VFSUnregisterDefaultDirectory(const Char *fileTypeStr,
                                  UInt32 mediaType)

I won't discuss them all in detail, but rather highlight some valuable points. First off, VFSDirCreate and VFSFileCreate don't open a folder or file. You still should open it manually in case you want to perform any operations on this file or folder.

The second thing I'd like to mention is a notion of a "default directory." I have already talked about it in my previous article, but let's repeat it here as well. Palm OS 4.x and higher has a mechanism that allows mapping file extensions or MIME types to specific folder names. Such a mechanism gives you a convenient way to determine where data files are (or should be) stored for a given expansion slot. The last three functions from the list above handle all possible situations you might have. You probably will want to define your own default directory to keep data that is specific to your application. Thus, you have a clue about how to do it.

Exploring File I/O Stuff

Well, I guess you won't be satisfied only by manipulating folders or files. A real application usually needs to perform some I/O operations, loading and saving its data. Here, you have a number of options.

If you keep your data in some format other that PDB or PRC, you can use VFSFileXXX functions to get direct access to such data. Usually, expansion cards contain a large amount of information, so this is the preferable way to manage expansion-card located data. You can't use Data Manager to manipulate native Palm databases stored on expansion cards.

The next sample code demonstrates how to sequentially save to the file some messages located on an expansion slot:

FileRef rFile;

// volRefNum is obtained earlier
Err err = VFSFileOpen(volRefNum, "/PALM/test.log",
                      vfsModeCreate|vfsModeWrite, &rFile);
if(err == errNone)
{
   err = VFSFileSeek(rFile,vfsOriginEnd,0);
   Char szLog[255];
   UInt32 nNumBytesWritten = 0;
   for (int i = 0; i < 100; i++)
   {
      StrPrintF(szLog,"Line #%d\r\n",i);
      err = VFSFileWrite(rFile, StrLen(szLog), (const void *)szLog,
                         nNumBytesWritten);
   }
   VFSFileClose(rFile);
}

This code is pretty similar to regular I/O programming under Windows or Unix. All this code does is open the file, set current file pointer to the end, and append the next line. It's as easy as possible.

Nevertheless, you may get read-only access to data and resources saved on expansion cards. The following funcitions are all about this kind of stuff:

Err VFSFileDBGetResource(FileRef ref, DmResType type, DmResID resID,
                         MemHandle *resHP)
Err VFSFileDBInfo(FileRef ref, Char *nameP,
                  UInt16 *attributesP, UInt16 *versionP,
                  UInt32 *crDateP, UInt32 *modDateP,
                  UInt32 *bckUpDateP, UInt32 *modNumP,
                  MemHandle *appInfoHP, MemHandle *sortInfoHP,
                  UInt32 *typeP, UInt32 *creatorP,
                  UInt16 *numRecordsP)
Err VFSFileDBGetRecord(FileRef ref, UInt16 recIndex,
                       MemHandle *recHP,
                       UInt8 *recAttrP, UInt32 *uniqueIDP)

Their usage and syntax are equivalent to DmGetRecord and so forth functions; the only difference is that they work with data stored on an expansion card.





Page 1 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel