文件流与存储流

symbian 的任何对像都可以流化,只要有公共的 ExternalizeL 及  InternalizeL 方法即可,这两个方法的定义为:

void ExternalizeL(RWriteStream& aStream) const;      


       void InternalizeL(RReadStream& aStream) ;

注意:任何已定义 ExternalizeL 及 InternalizeL 的类都可以使用 << 及 >> 进行外部或内部化

对于定义有 ExternalizeL 及 InternalizeL 的类如果有类成员,则在流化时可以从拥有者的 ExternalizeL 中
调用类成员的 ExternalizeL,如:

void CStudent::ExternalizeL(RWriteStream& aStream)      


       {      


           iTeacher->ExternalizeL(aStream);      


       }

文件流常用 RFileWriteStream 及 RFileReadStream 来操作文件。

存储基本上是流的集合,可以存储多种数据类型,主要来看一下 CDirectFileStore ,要通过 #include<s32store.h> 添加引用,library 也要添加estor.lib
初始化一个 CDirectFileStore 可以通过 Create 或 From 或 Replace 等 ,Create 用于不存在一个文件,From 用于通过一个已经打开的文件,Replace
是对于没有的文件则创建,存在的文件进行替换。

如果已经创建一个 CDirectFileStore ,则可以通过一个 SetTypeL 去指定存储的类型

再创建一个用于流入的对像 RStoreWriteStream 或 RStoreReadStream 对像,这个对像创建时指定一个 CDirectFileStore 对像,然后对这个RStoreWriteStream
或 RStoreReadStream 进行流入或流出操作,在创建一个 RStoreWriteStream 或 RStoreReadStream 时会返回一个 TStreamId 对像,这个对像用来唯一标识一个流
通过 CStreamDictionary 类可以将一个流ID与一个唯一值绑定起来,对于 CStreamDictionary 常用于存储到 root,存储 CStreamDictionary 时也需要通过
RStoreWriteStream 来流入,然后用 CDirectFileStore的SetRoot方法去指定。

RStoreWriteStream 处理完后,要通过 CommitL()提交,CDirectFileStore 也需要通过 Commit()提交

下面是练习的代码,根据上面说的再来看代码就能更清楚的理解了

#include        "       FileStore.h       "       
#include        <       e32base.h       >       
#include        <       e32std.h       >       
#include        <       e32cons.h       >                          //        Console       
       #include        <       s32file.h       >       
#include        <       f32file.h       >       
#include        <       s32std.h       >       
#include        <       s32stor.h       >       


       //         Constants       

_LIT(KTextConsoleTitle,        "       Console       "       );
_LIT(KTextFailed,        "        failed, leave code = %d       "       );
_LIT(KTextPressAnyKey,        "        [press any key]\n       "       );


       //         Global Variables       

LOCAL_D CConsoleBase       *        console;         //        write all messages to this

       //        定义两个流 id       
       LOCAL_D        const        KStuDataStreamId       =       0x101F613F       ;
LOCAL_D        const        KTeachDataStreamId       =       0x101F6140       ;


       class        CStudent:       public        CBase
{
       public       :
           static        CStudent       *        NewL(TDesC       &        aName,TInt32 aNo,TInt32 aScore);
           static        CStudent       *        NewLC(TDesC       &        aName,TInt32 aNo,TInt32 aScore);
           ~       CStudent();

           static        CStudent       *        NewL(RReadStream       &        aStream);
           static        CStudent       *        NewLC(RReadStream       &        aStream);
       public       :
           void        ExternalizeL(RWriteStream       &        aStream)        const       ;
           void        InternalizeL(RReadStream       &        aStream);
           void        Display();
    CStudent();
       private       :
    CStudent(TInt32 aNo,TInt32 aScore);
           void        ConstructL(TDesC       &        aName);
       private       :
    HBufC       *        iName;
    TInt32 iNo;
    TInt32 iScore;
};

CStudent       *        CStudent::NewL( TDesC       &        aName,TInt32 aNo,TInt32 aScore )
{
    CStudent       *        self        =        CStudent::NewLC(aName,aNo,aScore);
    CleanupStack::Pop();
           return        self;
}

CStudent       *        CStudent::NewL( RReadStream       &        aStream )
{
    CStudent       *        self        =        CStudent::NewLC(aStream);
    CleanupStack::Pop();
           return        self;
}
CStudent       *        CStudent::NewLC( TDesC       &        aName,TInt32 aNo,TInt32 aScore )
{
    CStudent       *        self        =               new       (ELeave) CStudent(aNo,aScore);
    CleanupStack::PushL(self);
    self       ->       ConstructL(aName);
           return        self;
}

CStudent       *        CStudent::NewLC( RReadStream       &        aStream )
{
    CStudent       *        self        =               new       (ELeave)CStudent();
    CleanupStack::PushL(self);
    self       ->       InternalizeL(aStream);          //        同化 ?为什么要这样呢       
                  return        self;
}
CStudent::       ~       CStudent()
{
    delete iName;
    iName        =        NULL;
}

       void        CStudent::ExternalizeL( RWriteStream       &        aStream )        const       
{
    aStream.WriteInt32L(iName       ->       Des().MaxLength());         //        写入最大长度       
           aStream       <<*       iName;             //        外化姓名       
           aStream.WriteInt32L(iNo);
    aStream.WriteInt32L(iScore);
}

       void        CStudent::InternalizeL( RReadStream       &        aStream )
{
           if        (iName        ==        NULL)
    {
        delete iName;
        iName        =        NULL;
    }
    TInt32 max ;
    max        =        aStream.ReadInt32L();
    iName        =        HBufC::NewL(aStream,max);
    iNo          =        aStream.ReadInt32L();
    iScore        =        aStream.ReadInt32L();
}

       void        CStudent::Display()
{
    _LIT(Kfmt,       "       name=%S\nno=%d\nscore=%d\n       "       );
    console       ->       Printf(Kfmt,iName,iNo,iScore);
    console       ->       Getch();
}

CStudent::CStudent()
{
    
}

CStudent::CStudent( TInt32 aNo,TInt32 aScore )
{
    iNo        =        aNo;
    iScore        =        aScore;
}

       void        CStudent::ConstructL( TDesC       &        aName)
{
    iName        =        aName.AllocL();    
}

              //       
       class        CTeacher:       public        CBase
{
       public       :
           static        CTeacher       *        NewL(TDesC       &        aName,TInt32 aNo,TInt32 aAge);
           static        CTeacher       *        NewLC(TDesC       &        aName,TInt32 aNo,TInt32 aAge);
    
           ~       CTeacher();
    

           static        CTeacher       *        NewL(RReadStream       &        aStream);
           static        CTeacher       *        NewLC(RReadStream       &        aStream);
       public       :
           void        ExternalizeL(RWriteStream       &        aStream)        const       ;
           void        InternalizeL(RReadStream       &        aStream);
           void        Display();
    CTeacher();
       private       :
    CTeacher(TInt32 aNo,TInt32 aAge);
           void        ConstructL(TDesC       &        aName);
       private       :
    HBufC       *        iName;
    TInt32 iNo;
    TInt32 iAge;
};

CTeacher       *        CTeacher::NewL( TDesC       &        aName,TInt32 aNo,TInt32 aAge )
{
    CTeacher       *        self        =        CTeacher::NewLC(aName,aNo,aAge);
    CleanupStack::Pop();
           return        self;
}

CTeacher       *        CTeacher::NewL( RReadStream       &        aStream )
{
    CTeacher       *        self        =        CTeacher::NewLC(aStream);
    CleanupStack::Pop();
           return        self;
}
CTeacher       *        CTeacher::NewLC( TDesC       &        aName,TInt32 aNo,TInt32 aAge )
{
    CTeacher       *        self        =               new       (ELeave)CTeacher(aNo,aAge);
    CleanupStack::PushL(self);
    self       ->       ConstructL(aName);
           return        self;
}

CTeacher       *        CTeacher::NewLC( RReadStream       &        aStream )
{
    CTeacher       *        self        =               new       (ELeave)CTeacher();
    CleanupStack::PushL(self);
    self       ->       InternalizeL(aStream);
           return        self;
}
CTeacher::       ~       CTeacher()
{
    delete iName;
    iName        =        NULL;

}

CTeacher::CTeacher()
{
    
}

CTeacher::CTeacher( TInt32 aNo,TInt32 aAge )
{
    iNo        =        aNo;
    iAge        =        aAge;
}
       void        CTeacher::ExternalizeL( RWriteStream       &        aStream )        const       
{
    aStream.WriteInt32L(iName       ->       Des().MaxLength());
    aStream       <<*       iName;
    aStream.WriteInt32L(iNo);
    aStream.WriteInt32L(iAge);
}

       void        CTeacher::InternalizeL( RReadStream       &        aStream )
{
           if        (iName        !=        NULL)
    {
        delete iName;
        iName        =        NULL;
    }
    TInt32 max;
    max        =        aStream.ReadInt32L();
    iName        =        HBufC::NewL(aStream,max);
    iNo          =        aStream.ReadInt32L();
    iAge         =        aStream.ReadInt32L();
         
}

       void        CTeacher::Display()
{
    _LIT(Kfmt,       "       Name=%S\nNo=%d\nAge=%d\n       "       );
    console       ->       Printf(Kfmt,iName,iNo,iAge);
    console       ->       Getch();
}

       void        CTeacher::ConstructL( TDesC       &        aName )
{
    iName        =        aName.AllocL();
}


       void        StoreL(RFs aFs,TDesC       &        aFileName)
{
    _LIT(KName1,       "       hewei       "       );
    _LIT(KName2,       "       hewei_2       "       );
    _LIT(KName3,       "       Jianzhou_3       "       );
    _LIT(KName4,       "       Jianzhou_4       "       );

    TBuf       <       10       >        name1(KName1);
    TBuf       <       10       >        name2(KName2);
    TBuf       <       10       >        name3(KName3);
    TBuf       <       10       >        name4(KName4);
    
    CStudent       *        stu1        =        CStudent::NewL(name1,       1       ,       80       );
    CStudent       *        stu2        =        CStudent::NewL(name2,       2       ,       90       );
    CTeacher       *        tec1        =        CTeacher::NewL(name3,       1       ,       25       );
    CTeacher       *        tec2        =        CTeacher::NewL(name4,       2       ,       30       );

    CArrayFixFlat       <       CStudent       >*        stuList       =               new       (ELeave)CArrayFixFlat       <       CStudent       >       (       4       );
    CArrayFixFlat       <       CTeacher       >*        tecList       =               new       (ELeave)CArrayFixFlat       <       CTeacher       >       (       4       );

    stuList       ->       AppendL(       *       stu1);
    stuList       ->       AppendL(       *       stu2);
    tecList       ->       AppendL(       *       tec1);
    tecList       ->       AppendL(       *       tec2);

    CFileStore       *        store       =       CDirectFileStore::ReplaceLC(aFs,aFileName,EFileWrite);
    store       ->       SetTypeL(TUidType(store       ->       Layout()));

    CStreamDictionary       *        dictionary        =        CStreamDictionary::NewLC();

    RStoreWriteStream stuStream;         //        写入流       
           TStreamId sid        =        stuStream.CreateLC(       *       store);
    TInt32 numberOfStudents        =        stuList       ->       Count();
    stuStream       <<       numberOfStudents;         //        写入数组长度       
                  int        i;
           for        (i       =       0       ;i       <       numberOfStudents;i       ++       )
    {
        (       *       stuList)[i].ExternalizeL(stuStream);          //        外部化数组元素       
           }
    stuStream.CommitL();
    CleanupStack::PopAndDestroy();

    RStoreWriteStream tecStream;
    TStreamId tId        =        tecStream.CreateLC(       *       store);
    TInt32 numberOfTechers        =        tecList       ->       Count();
    tecStream       <<       numberOfTechers;
           for        (i       =       0       ;i       <       numberOfTechers;i       ++       )
    {
        (       *       tecList)[i].ExternalizeL(tecStream);
    }
    tecStream.CommitL();
    CleanupStack::PopAndDestroy();

    dictionary       ->       AssignL(TUid::Uid(KStuDataStreamId),sid);
    dictionary       ->       AssignL(TUid::Uid(KTeachDataStreamId),tId);

    RStoreWriteStream root;             //        根流       
           TStreamId rootid        =        root.CreateLC(       *       store);
    root       <<*       dictionary;
    root.CommitL();
    CleanupStack::PopAndDestroy();         //        root       
           CleanupStack::PopAndDestroy();         //        dictionary       
           store       ->       SetRootL(rootid);
    store       ->       Commit();
    CleanupStack::PopAndDestroy();        //        store       
       }

       void        RestoreL(RFs aFs,TDesC       &        aFileName)
{
    CArrayFixFlat       <       CStudent       >*        stuList        =               new       (ELeave)CArrayFixFlat       <       CStudent       >       (       10       );
    CleanupStack::PushL(stuList);
    CArrayFixFlat       <       CTeacher       >*        tecList        =               new       (ELeave)CArrayFixFlat       <       CTeacher       >       (       10       );
    CleanupStack::PushL(tecList);

    CFileStore       *        store        =        CDirectFileStore::OpenLC(aFs,aFileName,EFileRead);

    CStreamDictionary       *        dictionary        =        CStreamDictionary::NewL();

    RStoreReadStream rootStream;
    rootStream.OpenLC(       *       store,store       ->       Root());
    rootStream       >>*       dictionary;
    CleanupStack::PopAndDestroy();

    TStreamId sid        =        dictionary       ->       At(TUid::Uid(KStuDataStreamId));
    TStreamId tid        =        dictionary       ->       At(TUid::Uid(KTeachDataStreamId));

           //       CleanupStack::PopAndDestroy();        //        dict       

    RStoreReadStream readStuStream;
    readStuStream.OpenLC(       *       store,sid);
    TInt32 numberOfStus;
    readStuStream       >>       numberOfStus;
           for        (TInt i       =       0       ;i       <       numberOfStus;i       ++       )
    {
        CStudent       *        stu        =        CStudent::NewL(readStuStream);
        CleanupStack::PushL(stu);
        stuList       ->       AppendL(       *       stu);
        
         CleanupStack::Pop();
    }
    CleanupStack::PopAndDestroy();

    _LIT(kfmt,       "       list students:\n       "       );
           for        (i       =       0       ;i       <       numberOfStus;i       ++       )
    {
        (       *       stuList)[i].Display();
    }

           //        读出教师数据       
           RStoreReadStream readTecStream;
    readTecStream.OpenLC(       *       store,tid);
    TInt32 numberOfTec;
    readTecStream       >>       numberOfTec;

           for        (i       =       0       ;i       <       numberOfTec;i       ++       )
    {
        CTeacher       *        tec       =       CTeacher::NewL(readTecStream);
        CleanupStack::PushL(tec);
        tecList       ->       AppendL(       *       tec);
        CleanupStack::Pop();
    }
    CleanupStack::PopAndDestroy();        //        readTechStream;       

    _LIT(kfmt2,       "       list tech:\n       "       );
    console       ->       Printf(kfmt2);
           for        (i       =       0       ;i       <       numberOfTec;i       ++       )
    {
        (       *       tecList)[i].Display();
    }
    
    delete dictionary;
    CleanupStack::PopAndDestroy(store);
    CleanupStack::PopAndDestroy(       2       );        //        array list       
       }


       //         Local Functions       

LOCAL_C        void        MainL(       const        TDesC       &        aArgs)
    {
           //       
           //        add your program code here, example code below
           //       
           //       console->Write(_L("Hello, world!\n"));       
           RFs iFs;       //       文件会话       
           User::LeaveIfError(iFs.Connect());       //       connect to file server       
           _LIT(KFileName,       "       c:\\stuList1.txt       "       );
    TBuf       <       20       >        FileName(KFileName);
           //       StoreL(iFs,FileName);       
           RestoreL(iFs,FileName);
    iFs.Close();
    console       ->       Printf(_L(       "       Command line args: \       "       %       S\       "       \n       "       ),        &       aArgs);
    }

简单总结一下:

CDirectFileStore 去打开或创建一个文件,通过 RStoreWriteStream  来写入数据,对于多个流来说,要通过CStreamDictionary去保存这些流对像然后把 CStreamDictionary 保存成 CDirectFileStore 的 root(),RStoreReadStream 要先通过Root得到 CStreamDictionary ,再找到 RStoreReadStream进行读取数据。

 



安平2009@原创