2010/05/10 10:03 A.M.
文件服务器功能
文件,目录
盘符,卷标
解析文件名
说明:
User Library------>File Server
| X
Kernel ------>Device Drivers
以前是用RAM,手机断电后不可以存储信息
现在是用闪存,手机断电后可以存储信息
C 内存
D~Y 外接盘
Z ROM
文件名:
可以象PC一样具有长文件名,如:"c:/system/apps/company/hujin network"
注:这里的"c:/" 表示:C:/Symbian/8.0a/S60_2nd_FP2_SC/epoc32/wins/c
不支持 . 和 ..
介质类型:ROM RAM 扩展存储器(CF,MMC)
文件系统-VFAF
文件服务器会话
从客户端访问服务器
RFs类的一个实例
一个线程中允许有多个RFs对象
主要功能:数据传递,目录和文件管理
File Server<----RFs---->App
使用文件会话例子
_LIT(KDataFileName,"c://documents//hujin.data");
...
RFs iFs;
iFs.Connect();
RFile iFile;
iFile.Open(iFs,KDataFileName);
//read or write to the file
iFile.Close();
iFs.Close();
...
文件会话操作
GUI应用程序只需使用iCoeEnv->FsSession()
文件系统相关的操作
操作当前目录
创建、删除、重命名目录
删除或重命名文件
修改文件或目录属性
操作磁盘和卷标
其它操作
文件类RFile
打开操作:Open(),Create(),Replace(),Temp()
其他操作:Read(),Write(),Rename(),Lock(),Unlock()
支持多种读写模式:共享读、独占写或者共享写
写文件
_LIT(KFile,"c://hujin.txt");
RFile iFile;
iFile.Create(iFs,KFile,EFileWrite);
//write to the file
_LIT(KText,"hujin network!");
TBufC<30> buf(KText);
TInt err;
err=iFile.Write(buf); //写成功返回KErrNone,否则返回错误值
User::LeaveIfError(err); //写出错抛出异常
iFile.Close();
读文件
_LIT(KFile,"c://hujin.txt");
RFile iFile;
iFile.Open(iFs,KFile,EFileRead);
//Read from the file
TBufC<30> buf;
TInt err;
err=iFile.Read(buf); //写成功返回KErrNone,否则返回错误值
User::LeaveIfError(err); //写出错抛出异常
iFile.Close();
文件会话类RFs
列出目录中的文件
RFs iFs;
CDir* fileList;
_LIT(KDirectory,"c://hujin//");
User::LeaveIfError(iFs.GetDir(KDirectory,KEntryAttNormal,ESortByName,fileList));
移动文件到其他目录
_LIT(KPath1,"c://hujin//hujin.txt");
_LIT(KPath2,"c://hujin//hujinnetwork//hujin.txt");
User::LeaveIfError(iFs.Rename(KPath1,KPath2));
另外还可以用RFs::Replace()和CFileMan::Move()移动文件
TInt Replace(const TDesC &anOldName, const TDesC &aNewName);
TInt Move(const TDesC &anOld, const TDesC &aNew, TUint aSwitch=EOverWrite);
删除文件
文件必须已经关闭,且非只读
删除操作:
_LIT(KFilename,"c://hujin.txt");
User::LeaveIfError(iFs.Delete(KFilename));
注:RFs::Delete()不支持通配符
删除多个文件用CFileMan::Delete()
列出目录
RFs iFs;
CDir* dirList;
_LIT(KDirectory,"c://hujin//");
User::LeaveIfError(iFs.GetDir(KDirectory,KEntryAttMaskSupported,ESortByName,dirList));
//KEntryAttMaskSupported: return contains a filtered list of directory entries only.
分别列出目录和文件
RFs iFs;
CDir* dirList,fileList;
_LIT(KDirectory,"c://hujin//");
User::LeaveIfError(iFs.GetDir(KDirectory,KEntryAttNormal,ESortByName,fileList,dirList));
//KEntryAttNormal: return contains a filtered list of directory and file entries.
创建目录
_LIT(KDirectory,"c://hujin//");
User::LeaveIfError(iFs.MkDir(KDirectory));
删除目录(只能删除空目录)
_LIT(KDirectory,"c://hujin//");
User::LeaveIfError(iFs.RmDir(KDirectory));
磁盘与卷(分区)
列出所有可用的磁盘 RFs::DriveList();
获取磁盘的信息(介质类型,介质属性等) RFs::Drive();
获取卷信息(卷名,ID,大小,空闲空间) RFs::Volume();
解析文件名
TParseXXX类允许开发人员查询或控制文件名
TParseBase具有标准的方法,如:Drive(),Path(),Name(),Ext()等
其他方法如 AddDir()将当前文件的目录加入到文件名前
PopDir()每调用一次,将文件名所在目录往上提一级,直到根目录时报错时,停止
TParsePtr和TParsePtrC属于轻量级的
TParse属于比较大的对象,需要时才使用,在堆上分配
写文件流RFileWriteStream
为什么使用写文件流RFileWriteStream,而不用RFile::Write()
当要写入大量数据,用RFileWriteStream更安全,而RFile::Write()不方便
RFile::Write()马上将数据发送给服务器,RFile::Flush()则将服务器端的buffer写到文件中;
RFileWriteStream是将数据保存在线程缺省堆中,RFileWriteStream::Flush()则是将客户端buffer中的数据通过调用RFile的方法写入文件
如果写文件包含了很多此操作,每次的数据量都较小,如果直接向Server端发送,将产生很多的消息,这样将影响文件服务器的性能。
若采用RFileWriteStream,则将减少向服务器发送消息的次数,这样将减轻文件服务器的负担。
通过流写文件例子
RFileWriteStream rws;
rws.PushL();
TInt err;
_LIT(KFile,"c://hujin.txt");
err=rws.Replace(iFs,KFile,EFileWrite);
User::LeaveIfError(err);
_LIT(KText,"hujin network!");
TBufC<30> buf(KText);
rws << buf;
rws.Flush();
CleanupStack::PopAndDestroy(rws);
通过流读文件例子
RFileReadStream reader;
reader.PushL();
TInt err;
TBufC<30> buf;
_LIT(KFile,"c://hujin.txt")
err=reader.Open(iFs,KFile,EFileRead);
User::LeaveIfError(err);
reader>>buf;
CleanupStack::PopAndDestroy(reader);
流:一个二进制序列,一个或多个对象的外在表现,一个对象可以通过外在化(Externalising)形成二进制的流,这个过程就是将类的成员变量按一定顺序以二进制的形式写入流的过程/
Stream ID:TStreamId类型,指向其他流的指针,其他流包含了其他对象的数据
流网络:对于一个复杂对象而言,可能包含一个很大的对象网络,因此常需要推迟某些对象的加载(到内存)
因此,可能有两种方法来表示一个对象:
通过流的StreamId,该流包含了对象的外化(如果它不在内存中的话)
通过指针,如果它在内存中(即已经加载)的话
常用Swizzle类(瘦小高效的容器)来处理这种双向表示,Swizzle可用的模板包括:
TSwizzleC<class T>
TSwizzle<class>
一个Swizzle类的外化通常包含两个处理过程:外化内存中的对象到流;外化产生的StreamId
File Store
在将应用程序数据保存到外部文件之前,首先需要在文件中创建一个Store
然后可以在store中创建流来保存各个对象
每个流id都会与UIDs组成各个映射关系,并保存在一个独立的流中,这个流被称为流字典,每个file store仅能有一个流字典
流字典的stream id将被当作store的根流
这种将流分别存储的方法比将所有数据保存在一起效率更高
File Store步骤
创建流字典
创建、写入、关闭文件数据流
保存Id到流字典中
保留app identifier到流字典
将流字典写入流中,关闭store
将包含流字黄的流设置成为根流
Stream Stores: 一旦流已经营承包保存到文件store中,将不能被替换、删除、修改等;通过store,只是可以更好的访问存储的数据
_LIT(KFile,"c://hujin.txt");
CFileStore* store=CDirectFileStore::CreateLC(iFs,KFile,EFileWrite);
对象外化:如果一个类需要以流的方式存储,则要实现一个外化方法
class CExample : public CBase{
public:
void ExternalizeL(RWriteStream& aStream) const;
...
};
void CExample::ExternalizeL(RWriteStream& aStream) const{
//写三个数据
aStream.WriteInt32L(iIntValue);
aStream.WriteReal64L(iRealValue);
aStream << iBuffer;
iA->ExternalizeL(aStream);
}
内化:重新构建
class CExample : public CBase{
void InternalizeL(RReadSTream& aStream);
...
};
void CExample::ExternalizeL(RReadSTream& aStream) const{
//读三个数据
iIntValue=aStream.ReadInt32L();
iRealValue=aStream.ReadReal64L();
aStream >> iBuffer;
iA->InternalizeL(aStream);
}
--------------------------0:31 2009/9/22--------------------------------
文件及流操作练习
学习例子:Examples/base/filestores/
Series60_v20/Series60Ex/shopinglis/
练习:GUIClock7
提示:
重载CAknDocument::OpenFileL()
修改资源文件中的RESOURCE TBUF,设置保存文件的缺省名字
重载CAknDocument::StoreL()
重载CAknDocument::RestoreL()
在处理Exit事件时调用SaveL()
将要保存的时间实现成TSetting(实现InternalizeL和ExternalizeL)
需要修改菜单处理部分(修改设置和退出)
添加库文件estor.lib