Part10 FileSysStore
Part10 FileSysStore
This work is licensed under the Creative Commons Attribution-Share Alike 2.0 UK: England & Wales License.
To view a copy of this license, visit http://creativecommons.org/licenses/bysa/2.0/uk/ or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California,
94105, USA.
File Sys Store
RFs fs;
Connect the session
User::LeaveIfError(fs.Connect());
Closes fs if a leave occurs
CleanupClosePushL(fs);
Create a file
...
_LIT(KASDExampleIni, "c:\\ASDExample.ini");
A subsession which represents a file, as below
RFile file;
User::LeaveIfError(file.Create(fs, KASDExampleIni,
EFileRead|EFileWrite|EFileShareExclusive));
Closes file if a leave occurs
CleanupClosePushL(file);
TBuf8<32> buf;
Submit a read request using the subsession
...
User::LeaveIfError(file.Read(buf));
Clean up the RFile subsession and RFs session
...
This calls RFile::Close() on file
and RFs::Close on fs
CleanupStack::PopAndDestroy(2, &fs);
Replace()
• Used to move a file to a different location
NotifyChange()
• An asynchronous request for notification of changes to files,
directories or directory entries
NotifyChangeCancel()
• Used to cancel the outstanding request
ReadFileSection()
• Used to “peek” at file data without opening the file
AddFileSystem(), MountFileSystem(),
DismountFileSystem() and RemoveFileSystem()
• Used to dynamically add and remove file system plug-ins
• That extend the file server types Symbian OS can support
An RFile object
• Represents access to a named, individual file
Providing functions to
• Open, create or replace the file
• Or to open a temporary file
• To read from and write to the file
RFile::Open()
• Used to open an existing file; an error is returned if it does not
already exist
RFile::Create()
• Used to create and open a new file
• An error - KErrAlreadyExists - is returned if the file already
exists
RFile::Replace()
• Creates a file if it does not yet exist
• Deletes an existing version of the file and replaces it with an empty
one if it does exist
RFile::Temp()
• Opens a new temporary file and assigns a unique name to it
A common pattern
• Is to call Open() to attempt to open an existing file
• Then call Create() if it does not yet exist
For example
• When using a log file, an existing log file should not be
replaced
• But simply have data appended to it:
RFile logFile;
TInt err=logFile.Open(fsSession,fileName,shareMode);
if (err==KErrNotFound)
err=logFile.Create(fsSession,fileName,shareMode);
For example
• To open a file as writable and shared with other clients:
RFile file;
_LIT(KFileName,"ASDExample.ini");
file.Open(fsSession,KFileName,EFileWrite|EFileShareAny);
RFs::ReadFileSection() method
• Can read from a file without opening it
• Thus the contents of a file can never be truly locked
• Either through use of RFile::Open() methods with
EFileShareExclusive flags
• Or by calling RFile::Lock()
RFs::ReadFileSection()
• Is used by Apparc and the recognizer framework to
determine the type of a file by rapid inspection of its contents.
Although
• Neither the asynchronous Read() nor the
asynchronous Write() method can be cancelled
In all cases
• 8-bit descriptors are used ...
As a consequence
• Of using 8-bit descriptors
Files on Symbian OS
• Are identified by a file name specification which may be up to
256 characters in length
Symbian OS applications
• Do not normally rely on the extension to determine the file
type
• They use one or more UIDs stored within the file
• To ensure that the file type matches the application
On Symbian OS phones
• The z: drive is always reserved for the system ROM
• The c: drive is always an internal read–write drive
• On some phones may have limited capacity
File names
• Are constructed and manipulated using the TParse class and its
member functions
• For example, to set an instance of TParse to contain the file
specification c:\Documents\Oandx\Oandx.dat:
_LIT(KFileSpec, "c:\\Documents\\Oandx\\Oandx.dat");
TParse fileSpec;
fileSpec.Set(KFileSpec,NULL,NULL);
For example:
TParse::Set()
• Takes three parameters
For example
• It is more efficient to read once from a file into one large buffer
• Then access and manipulate this client-side
• Rather than make multiple read requests for smaller sections of a
file
• Know the reasons why use of the stream APIs may be preferred
over use of RFile
• Understand how to use the stream and store classes to manage
large documents most efficiently
• Be able to recognize the Symbian OS store and stream classes
and know the basic characteristics of each (for example base class,
memory storage, persistence, modification, etc.)
• Understand how to use ExternalizeL() and operator << with
RWriteStream to write an object to a stream, and
InternalizeL() and operator >> with RReadStream to read it
back
• Recognize that operators >> and << can leave
Streams
A Symbian OS stream
• Is the external representation of one or more objects
Externalization
• Is the process of writing an object’s data to a stream
Internalization
• The reverse process - reading an object’s data from a
stream
The stream
• May reside in a variety of media
• Including stores, files or memory
• Streams provide an abstraction layer over the final
persistent storage media.
Streams
Streams
The representation
• Of each item of data must also have an unambiguously defined
length
• Special care is needed when externalizing data types such as
TInt
• Whose internal representation may vary in size between different
processors and/or C++ compilers
Streams
Internalization code
• Which restores the objects by reading from the stream
• Must therefore follow exactly the same order used to externalize
them
Streams
For example:
Streams
The RReadStream and RWriteStream base
classes
• Provide a variety of WriteXxxL() and ReadXxxL()
functions
• That handle specific data types
• Ranging from 8-bit integers e.g. WriteInt8L()
• To 64-bit real numbers e.g. WriteReal64L()
Streams
The raw data functions
• Should be used with caution:
2. A call to ReadL()
• Must read exactly the same amount of data as was written by the
corresponding WriteL() call
• This can be ensured by writing the length immediately before the data
• Or terminating the data with a uniquely recognizable delimiter
Streams
A common pattern:
• Operator << is used to externalize the data
• Operator >> to internalize it
• Can be used for all built-in types
• Except those like TInt whose size is unspecified and compiler-
dependent
On Symbian OS
• A TInt is only specified to be at least 32 bits
• It may be longer!
• Thus externalizing it with operator << would produce an external
representation of indefinite size
So ...
• The maximum length of the value
• Is used to select an appropriate internalization and externalization
method
Fundamentals of Symbian C++ 46
File Sys Store
Streams
For example
• If the value stored in a TInt can never exceed 16 bits
• RWriteStream::WriteInt16L() can be used to externalize it
• RReadStream::ReadInt16L() to internalize it:
TInt i = 1234;
writer.WriteInt16L(i);
...
TInt j = reader.ReadInt16L();
...
// Cleanup etc
Streams
class TAsdExample
{
public:
...
void ExternalizeL(RWriteStream& aStream) const;
void InternalizeL(RReadStream& aStream);
...
};
Streams
For such a class
• Externalization can use either:
TAsdExample asd;
...
writer << asd; // writer is RFileWriteStream
// initialized and leave-safe
• Or
TAsdExample asd;
...
asd.ExternalizeL(writer); // writer is
RFileWriteStream
// initialized and leave-safe
Streams
Stores
Stores
A Symbian OS store
• Is a collection of streams
• Generally used to implement the persistence of objects
Stores
Stores
An important distinction
• Between the different store types is whether or not they are
persistent
A persistent store
• Can be closed and re-opened and its content accessed
• The data in such a store continues after a program has closed it
• Even after the program itself has terminated
• A file-based store is persistent
Stores
Store class hierarchy
CStreamStore
CEmbeddedStore CFileStore
CDirectFileStore CPermanentFileStore
Stores
Logical view of a persistent store
root stream 1
stream 1
stream 2
Stores
Stores
Stores
Other applications
• Such as games which store level data hold all their data in
memory
• load or save the data in its entirety
For comparison
• The following code creates a permanent file store:
RStoreWriteStream stream;
TStreamId id = stream.CreateLC(*store);
TInt16 i = 0x1234;
stream << i;
stream.CommitL();
CleanupStack::PopAndDestroy();
dictionary->AssignL(aAppUid,id);
RStoreWriteStream rootStream;
TStreamId rootId = rootStream.CreateLC(*store);
rootStream << *dictionary;
rootStream.CommitL();
CleanupStack::PopAndDestroy(); // rootStream
...
store->SetRootL(rootId);
store->CommitL();CleanupStack::PopAndDestroy(); // store
• The store’s destructor takes care of closing the file and freeing any
other resources
To counteract this
• The stream store API includes functions to compact the store
• By removing replaced or deleted streams
Note
It is important
• Not to lose a reference to any stream within the store
• This is analogous to a memory leak within an application
• Resulting in the presence of a stream that can never be accessed
or removed
Arguably
• Losing access to a stream is more serious than a memory leak
• As a persistent file store outlives the application that created it
Embedded Stores
A store
• May contain an arbitrarily complex network of streams
• Any stream may contain another stream — by including its ID
• A stream may itself contain an embedded store
It may be useful
• To store a collection of streams in an embedded store
• From the outside - the embedded store appears as a single
stream
• Can be copied or deleted as a whole without the need to
consider its internal complexities
Embedded Stores
Embedded Stores
Swizzles
Swizzles
Either by:
• Stream ID the stream contains the external representation of
that object
• Pointer - if the object is in memory
Swizzles