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