文件流与存储流

 

文件流与存储流

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@原创
qi_jianzhou@126.com

posted @ 2010-01-22 00:41  zziss  阅读(764)  评论(0编辑  收藏  举报