Wiley.Symbian.OS.C.plus.plus.for.Mobile.Phones.Aug.2007 (779890), страница 41
Текст из файла (страница 41)
Application developers should usethe private directory to store information private to an application (seeSection 9.3 for further details).7.3 File System ServicesThis section describes the basic low-level services that underlie all otherSymbian OS file-based services. These services are provided by a systemserver referred to as the file server or F32. Most F32 APIs can be found inthe public header file f32file.h.File SpecificationsAs with most computer operating systems, Symbian OS files are identifiedby a file name, which may be up to 256 characters in length.
A filespecification consists of:• a device, or drive, such as C:• a path, such as \Document\Unfiled , where the directory namesare separated by backslashes (\)• a file name• an optional file name extension, separated from the file name by aperiod (.).All file systems supplied by Symbian support the VFAT specification interms of character legality for file and directory names.The file server supports up to 26 drives, from labeled from A: to Z:.On Symbian OS phones, the Z: drive is always reserved for the systemROM and the C: drive is always an internal read–write drive, althoughon some phones it may have limited capacity.
Drives from D: onwardsmay be internal, or may contain removable media or a drive used for USBMass Storage access. You should not assume that you can write to allsuch drives; many phones have one or more read-only drives, in additionto the Z: drive.206FILES AND THE FILE SYSTEMSubject to the overall limit on the length of a file specification, adirectory name, file name or extension may be of any length. The filesystem preserves the case of such names, but all operations on the namesare case-independent.
Clearly, this means that you can’t have two ormore files in the same directory whose names differ only in the cases ofsome of their letters. File specifications for searching APIs may containthe wild cards ‘?’ (a single character) and ‘*’ (any sequence of characters)in any component other than the drive letter.Although most Symbian OS applications do not do so, you are free toinclude a file name extension in the specification of any file.
Symbian OSapplications do not always rely on the extension to determine the file’stype. Instead, they use one or more UIDs, stored within the file, to ensurethat the file type matches the application. For applications such as musicplayers or photo editors, the file being accessed may be subject to openstandards, such as MP3 or Jpeg, and therefore UIDs may not be used.Manipulating File NamesFile names may be constructed and manipulated using the TParseclass and its member functions.
For example, the following code sets aninstance of TParse to contain a file specification:_LIT(KFileSpec, "C:\\Private\\<application_UID>\\application.dat");TParse fileSpec;fileSpec.Set(KFileSpec, NULL, NULL);where <application_UID> is the 32-bit UID assigned to the application.Following this code, you can call TParse’s getter functions to determine the various components of the file specification. For example,fileSpec.Drive() contains the string "C:" and fileSpec.Path()contains "\Private\<application_UID>".The Set() function takes three text parameters: the first is a referenceto a TDesC, containing the file specification to be parsed; the secondand third parameters are pointers to two other TDesC descriptors, andeither or both may be NULL. If present, the second parameter (the relatedfile specification) is used to supply any missing components in the firstfile specification and the third parameter should point to a default filespecification, from which any components not supplied by the first andsecond parameters are taken.
Any path, file name or extension maycontain the wildcard characters ‘?’ or ‘*’, respectively representing anysingle character or any character sequence.A TParse owns an instance of TFileName, which is a TBuf<256>.This is a large object, with file names specified using 16-bit Unicodecharacters, and its use should be avoided if possible. If you can, create aFILE SYSTEM SERVICES207smaller buffer to contain the file specification and use a TParsePtr (referencing a modifiable buffer) or a TParsePtrC (referencing a constantbuffer).File Server SessionsThe Symbian OS file server provides the basic services that allow userprograms to manipulate drives, directories and files, and to read and writedata in files.As with all servers, the file server uses session-based communicationto convert a client-side operation into a message that is sent to the server.The requested function is performed in the server, and then any result ispassed back to the client.
In order to use the file server, you first need aconnected file server session, represented by an instance of the RFs class.The general pattern, ignoring error handling, for using the file server is:RFs session;session.Connect() ;...session.Close() ;Between connecting and closing the RFs, you can use it to openany number of files or directories, or to perform any other file-relatedoperations. If you wish, you may keep a file server session open forthe lifetime of your application.
It is preferable that you make sure thatall open file-based resources are correctly closed before you close thesession. In any case, when the session is closed, the server cleans up anyserver-side resources associated with the session.In fact, in a GUI application, you don’t need to open a file serversession, since the control environment already has an open RFs thatyou can access with iCoeEnv->FsSession(). Opening a file serversession is an expensive operation so, if at all possible, you should use theexisting session, rather than creating your own.The RFs class provides many useful operations related to the filesystem, including:• making,removingandrenamingdirectoriesMkDir(), MkDirAll(), RmDir() and Rename()using• deleting or renaming files using Delete() and Rename()• reading and changing directory and file attributes by means of Att(),SetAtt(), Modified() and SetModified()• notifying changes with NotifyChange() and NotifyChangeCancel()• manipulating drives and volumes using Drive(), SetDriveName(), Volume() and SetVolumeLabel()208FILES AND THE FILE SYSTEM• peeking at file data without opening the file by using ReadFileSection()• adding and removing file systems with AddFileSystem(), MountFileSystem(), DismountFileSystem() and RemoveFileSystem()• querying and creating the private path for an application usingPrivatePath() and CreatePrivatePath()These functions, and their use, are documented in the SDKs.Most RFs-related functions are stateless – that is, the results of afunction call don’t depend on any functions previously called.
That’swhy you can usually use the control environment’s RFs for your ownpurposes. However, RFs does have one item of state: its current directory.When you open an RFs, its current directory is set to a default location,the root of the C: drive (c:\.), but you can use SetSessionPath()to change the current directory. The session path must consist of atleast a drive and root, as the default location does, and any number ofsubdirectories can also be specified. All subsequent file server operationsinvolving file names use the session path unless the file name is fullyspecified, starting with a drive letter.
The current session path for an RFscan be retrieved using SessionPath().The current directory includes the drive as well as directory names.There is no concept of one current directory per drive.If you manipulate, or rely on, the current directory, make sure you useyour own RFs rather than sharing one. In that case, you must also handleerrors associated with the session. How to handle them depends on theway that the session is stored. If it is declared as member data in one ofyour classes, with a class definition containing a line such as:RFs iFs;then it is sufficient to connect the file session (from a function that allowsleaves to occur) with:User::LeaveIfError(iFs.Connect() );and to close the session with:iFs.Close()in the class destructor.FILE SYSTEM SERVICES209If you declare the file server session on the stack, you need to take alittle more care.
You need to place the session on the cleanup stack andthe best way is to use CleanupClosePushL(), as follows:RFs myFs;User::LeaveIfError(myFs.Connect() );CleanupStack::CleanupClosePushL(myFs);...// file session operations that may leave...CleanupStack::PopAndDestroy() ;Remember that connecting a file server session is an expensive, timeconsuming operation, so you should only do it if there is a good reasonnot to share the one that exists in the control environment.RFs contains functions to manipulate a file system. However, thecontents of more than one individual file or directory may be opened atonce. If you had to have a separate file server session open for each fileopened, this would place a large burden on the file server. To avoid thisissue, files and directories are treated as Symbian OS subsessions.
Eachsubsession can be opened against a given session: the file server sessionis passed in as a parameter to the Open() function of the subsession andcan maintain the state of the file or work through a directory listing.DirectoriesA directory contains files and other directories, each of which is represented by a directory entry.
In Symbian OS, a TEntry object is used tocontain directory-entry information. TEntry objects contain membersrepresenting the size, attributes (hidden, read-only), modified date andname of a file or directory.The RDir class allows you to open a directory and read the entriesit contains. There are several different ways of reading the contents of adirectory. The most straightforward, but not necessarily the most efficient,way is illustrated in the following example:void ReadDirContentsL(RFs& aFs, const TDesC& aDirName){RDir myDir;TInt err;User::LeaveIfError(myDir.Open(aFs, aDirName,KEntryAttNormal| KEntryAttDir));TEntry currentEntry;FOREVER{err = myDir.Read(currentEntry);if (err){break; // No more entries, or some other error}210FILES AND THE FILE SYSTEM// Process this entry}myDir.Close()if (err != KErrEof) // EOF signifies no more entries to read{User::LeaveIfError(err);}}Each call to Read() reads a single entry, which is useful in caseswhere memory usage needs to be minimized.