文件流与存储流
文件流与存储流
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