Fundamentals of Symbian C++/File Server/zh-hans
文章信息
文件服务器负责全面地管理手机存储设备上的文件和目录,并为ROM、RAM、闪存、可移除媒体以及经由HTTP访问的远程文件系统提供一致的访问接口。文件服务器进程的可执行文件是EFILE.EXE, 它的客户端接口包含在名为EFSRV.DLL的DLL中:
RFs类是文件服务器的客户端句柄,该类继承自RSessionBase,它被用来操作驱动器、目录和文件。
RFile类和RDir类分别是针对单个文件和目录的句柄。它们被实现成RFs的子会话(sub-sessions),这样客户端使用一个RFs对象就能在单一的线程上下文中同时操作多个目录和文件。
Contents |
文件服务器会话
为了访问文件服务器,调用者必须首先创建一个文件服务器会话,即一个RFs类的实例。
初始化和清除
调用者必须首先调用RFs::Connect()初始化文件服务器会话,该方法返回一个错误码。如果初始化成功,则客户端负责关闭该文件服务器会话。如果该会话是一个本地变量,客户端应该使用清除栈(cleanup stack)保证程序在发生异常退出时会话也能被关闭。
RFs fs;
User::LeaveIfError(fs.Connect()); // 连接会话
CleanupClosePushL(fs); // 如果发生异常退出则通过清除栈关闭fs
... // 使用文件服务器
CleanupStack::PopAndDestroy(&fs); // 关闭会话
使用会话
文件服务器会话可以被用于大量的文件系统操作,包括:
- 打开、创建、删除和重命名文件与目录
- 设置目录和文件的属性
- 接收文件和目录变化的异步通知。
- 获取驱动器和磁盘的信息
- 添加或移除文件系统插件
文件
RFs类是文件系统的客户端会话,而RFile类是RFs类的子会话。一个RFile对象用于访问单个命名的文件。
初始化和清除
有四种方法可以初始化一个RFile对象:
| RFile::Open() | 通过指定文件名打开一个已有的文件,如果返回错误码KErrNotFound表明指定的文件不存在,如果返回错误码KErrAccessDenied表明指定文件正在被其它客户端以排他的方式读写。
其它常见的错误码有KErrPathNotfound, KErrPermissionDenied(表明进程无权访问指定的文件)和KErrBadName (表明文件名的格式不正确)。 |
| RFile::Create() | 新建并打开指定文件名的文件;如果返回错误码KErrAlreadyExists 表明指定的文件已经存在。 |
| RFile::Replace() | 如果指定文件名的文件不存在则新建,否则以一个空文件替换它。 |
| RFile::Temp() | 新建并打开一个临时文件,由系统指定唯一的文件名。 |
一个常用的模式是先调用Open()试图打开一个已有的文件(不会破坏该文件的数据),如果文件不存在则调用Create()创建它。
RFile logFile;
TInt err=logFile.Open(fsSession,fileName,shareMode);
if (err==KErrNotFound) // 如果文件不存在则创建它
{
err=logFile.Create(fsSession,fileName,shareMode);
}
同样地,客户端要负责通过调用RFile::Close()关闭已打开的文件,并通过清除栈保证本地的RFile变量在程序发生异常退出时被关闭。
文件模式
以上四个初始化方法均接受一个TUint类型的位掩码参数,该参数包含一组TFileMode值;它们代表了待打开文件的“访问模式”和“共享模式”。
访问模式用于指定以只读方式打开文件(EFileRead)或者以读写方式(EFileWrite)打开文件,它可以用位或运算合并共享模式。共享模式用于指定该文件被打开后是否允许其它RFile对象访问,如果允许的话是以只读方式还是其它方式访问。
读写二进制文件
RFile提供了Read()和Write()方法,分别用于将数据从文件中读取到一个可修改的8位描述符(TDes&)和将保存在不可修改的8位描述符(const TDesC8&)中的数据写入文件。
// 打开文件服务器连接
RFs fs;
User::LeaveIfError(fs.Connect());
CleanupClosePushL(fs);
// 打开Example.ini文件
_LIT(KExample,"c:\\Example.ini");RFile file;
User::LeaveIfError(file.Open(fs, KExample, EFileShareExclusive|EFileWrite));
CleanupClosePushL(fs);
// 写入文件
_LIT8(KWriteData,"Hello world");
User::LeaveIfError(file.Write(KWriteData));
// 从文件中读取
TBuf8<5> readBuf;
User::LeaveIfError(file.Read(readBuf));
// readBuf包含"Hello"
CleanupStack::PopandDestroy(2, &fs);
RFile提供了Read()和Write()的多种重载形式:
- 读写指定字节数的数据
- 从指定的偏移量开始读写文件
- 从指定的偏移量开始读写指定字节数的数据
- 以上方法的异步形式。
读写16位描述符
{icode|RFile}没有提供读写16位描述符数据的方法。推荐的方法是使用流(read or write stream)。
共享文件
打开的RFile对象可以在进程间传递:
- TransferToServer()和AdoptFromClient() 用于将RFile对象从客户端传递到服务器端
- TransferToClient() and AdoptFromServer()用于将RFile对象从服务器端传递到客户端
- TransferToProcess() and AdoptFromCreator()用户将RFile对象在进程间传递
如果想了解更多关于共享文件的细节,请查看Symbian Developer Library。
文件名
Symbian OS中的每个文件以一个最长256个字符的文件名标识。文件名的构成与DOS的文件名规范类似:
- 盘符,例如c:
- 路径,例如\Document\Unfiled\,其中目录名之间用反斜杠(\)分隔。
- 文件名
- 文件扩展名(可选),以点号(.)与文件名分隔。
文件名总长不能超过256个字符,在这个范围内对目录名、文件名或扩展名的长度并无限制。RFs::IsValidName()方法可以用于检查一个文件名是否有效。
Symbian平台的文件系统最多支持26个驱动器,即a:到z:。通常包括一个或多个只读驱动器,一个内置的非易失可读写驱动器,以及一个或多个可移除的非易失可读写驱动器。
内置的持久存储可读写驱动器可以通过调用RFs::GetSystemDriveChar返回,客户端程序不要假定它就是c:盘。
文件系统在执行文件操作时会保留文件名的大小写,但并不区分文件名大小写,即不能仅以大小写的变化来区别不同的文件和目录。
文件名可以用TParse类处理。如果在初始化TParse对象时传入一个完整的文件名(例如,{icode|z:\resource\apps\myapp.rsc}}),那么就可以用TParse提供的方法获得它的各个组成部分,即盘符、路径、文件名和扩展名。
使用文件服务器的良好的做法
TFileName可以容纳一个完整的文件名,实际上它是一个长度为256的16位可修改缓冲区描述符对象TBuf16<256>,由于它是一个很大的对象(512个字节),在使用过程中应该尽量避免在栈上创建它。
连接文件服务器会消耗内核资源和文件服务器的资源,因此一个良好的做法是尽可能地保留和重用文件服务器连接,例如在设计API时接受RFs对象或RFile对象的引用,而非传入文件名。此外,基于Symbian控件环境(CONE, Control Environment)的GUI应用程序可以调用CCoeEnv::FsSession()获取一个已连接的文件服务器会话。
在进行文件操作时应该通过缓冲尽量减少读写请求的次数。例如,每次从文件中读取一个字节的效率非常低:更好的方式是一次读取一大块数据到客户端的缓冲区中,然后逐字节访问缓冲区中的数据。C语言移植代码非常契合这一点,因为POSIX会缓冲客户端的读写,所以单字节读写非常快。
此外,Symbian文件服务器默认会保证在写入调用完成时(即同步调用返回时或异步调用的TRequestStatus完成时)将数据写入磁盘。这一点跟Linux操作系统非常不一样,在Linux里写入操作只是将数据保存到内存缓冲区中。
Note that this content was originally hosted on the Symbian Foundation developer wiki.



(no comments yet)