14.1 文件类和函数
wxWidgets 提供了一系列的平台无关的文件处理功能.在概览所有文件函数之前,我们先来看看几个主要的类。
wxFile 和 wxFFile
wxFile 类可以用来处理底层的文件输入输出.它封装了常用的用于操作整数文件标识符的标准 C 操作(打开关闭,读写,移动游标等),但是和标准 C 不同的是,它使用 wxLog 类来报告错误并且在析构函数中自动关闭文件.而 wxFFile 则提供缓冲的输入输出操作,内部使用的是 FILE 类型的指针。
你可以通过下面的方法创建一个 wxFile 对象:使用默认构造函数然后调用 Create 或者 Open 函数;或者直接在构造函数中指明文件名和打开模式(wxFile::read, wxFile::write 或 wxFile::read_write);或者直接使用已经存在的整数文件描述符(相关构造函数或者默认构造函数加 Attach 函数).Close 函数关闭当前使用的文件,文件也将在析构函数中视需要进行关闭。
从文件中读取数据使用 Read 函数,参数为一个 void和一个缓冲区大小,返回实际读取的数值大小或者 wxInvalidOffset 如果读取过程发生错误.使用 Write 函数将指定大小的 void类型的缓冲区写入文件,如果你希望写操作立即写到物理文件,你需要使用 Flush 函数。
Eof 函数用来检测当前的文件指针是否位于文件结尾的位置(而 wxFFile 的 Eof 函数只有在其读操作越过了文件结尾的时候才返回 True).你可以用 Length 函数返回文件的长度。
Seek 和 SeekEnd 函数将文件指针移动到相对于文件开始或者文件结尾的一个偏移位置.Tell 函数返回 wxFileOffset 类型的当前文件指针位置,这个类型在支持 64 位操作系统上是 64 位整数,否则是 32 位整数。
Access 函数是一个静态函数,用来判断某个文件是否可以以指定的模式打开,而 Exists 函数则用来判断指定的文件是否存在。
下面的代码演示了怎样使用 wxFile 打开一个文件并且将其内容读取到一个数组中:
#include "wx/file.h"
if (!wxFile::Exists(wxT("data.dat")))
return false;
wxFile file(wxT("data.dat"));
if ( !file.IsOpened() )
return false;
//文件大小
wxFileOffset nSize = file.Length();
if ( nSize == wxInvalidOffset )
return false;
// 将所有内容读取到一个数组中
wxUint* data = new wxUint8[nSize];
if ( fileMsg.Read(data, (size_t) nSize) != nSize )
{
delete[] data;
return false;
}
file.Close();
下面的代码则演示了怎样将一个文本框的所有内容写入到文件中:
bool WriteTextCtrlContents(wxTextCtrl* textCtrl,
const wxString& filename)
{
wxFile file;
if (!file.Open(filename, wxFile::write))
return false
int nLines = textCtrl->GetNumberOfLines();
bool ok = true;
for ( int nLine = 0; ok && nLine < nLines; nLine++ )
{
ok = file.Write(textCtrl->GetLineText(nLine) +
wxTextFile::GetEOL());
}
file.Close();
return ok;
}
wxTextFile
wxTextFile 提供了一种非常直接的方式来以行为单位读取和写入小型的文本文件。
使用 Open 函数将这个文本文件读取到内存中并且以行为单位进行分割,使用 Write 函数写回到文本文件.你可以使用 GetLine 函数或者直接按照数组的方式操作某个特定的行.或者使用 GetFirstLine,GetNextLine 和 GetPrevLine 进行遍历.AddLine 和 InsertLine 用来增加新行,RemoveLine 用来移除特定的行,Clear 函数则用来清空所有的行。
下面的例子演示了将文本文件中的每一行都增加一个前导文本的方法:
#include "wx/textfile.h"
void FilePrepend(const wxString& filename, const wxString& text)
{
wxTextFile file;
if (file.Open(filename))
{
size_t i;
for (i = 0; i < file.GetLineCount(); i++)
{
file[i] = text + file[i];
}
file.Write(filename);
}
}
wxTempFile
wxTempFile 是 wxFile 的一个派生类,它使用临时文件来写入数据,数据在 Commit 函数被调用之前不会被写入.如果你需要写一些用户数据,你可以将其写在临时文件里,它的好处是:如果遇到突然的断电或者应用程序不可知错误或者其它大的错误时,临时文件不会对磁盘上的文件系统造成任何伤害。
提示:文档/视图框架在创建一个输出流然后调用 SaveObject 的时候没有使用临时文件.你可以尝试重载其 DoSaveDocument 函数,在其中构建一个 wxFileOutputStream 并且让其使用一个临时文件 wxTempFile 对象,在全部数据写完以后,调用 Sync 函数和 Commit 函数将其写入临时文件。
wxDir
wxDir 是一个轻便的等价于 Unix 上的 open/read/closedir 函数的类,它支持枚举目录中的所有文件.wxDir 既支持枚举目录中的文件,也支持枚举目录中的子目录.它还提供了一个灵活的递归枚举文件的方法 Traverse 函数,和另外一种简单的方法: GetAllFiles 函数。
首先,你需要调用 Open 函数打开一个目录(或者通过构造函数直接赋值),然后调用 GetFirst 函数,参数为一个指向字符串类型的指针用来接收找到的文件名,一个可选的文件通配符(默认为所有文件) 和一个可选的选项.然后调用 GetNext 函数直到其返回 False.文件通配符可以是固定的文件名以及包含"*(匹配任意字符)"和"?"(匹配单个字符) 的通配符.选项参数可选的值为:wxDIR_FILES(所有文件), wxDIR_DIRS(所有文件夹),wxDIR_HIDDEN(隐藏文件) 以及 wxDIR_DOTDOT("."和"..") 以及它们的组合,默认值为除了最后一项的所有文件。
下面是一个例子:
#include "wx/dir.h"
wxDir dir(wxGetCwd());
if ( !dir.IsOpened() )
{
// 如果遇到这个情况,wxDir 已经显示了一个出错信息.
// 所以直接返回就可以了
return;
}
puts("Enumerating object files in current directory:");
wxString filename;
wxString filespec = wxT("*.*");
int flags = wxDIR_FILES|wxDIR_DIRS;
bool cont = dir.GetFirst(&filename, filespec, flags);
while ( cont )
{
wxLogMessage(wxT("%s\n"), filename.c_str());
cont = dir.GetNext(&filename);
}
如同上面注释中说的那样,如果 wxDir 打开的时候出现错误,将会弹出一个错误消息,如果想禁止这个消息,你可以临时通过设置 wxLogNull 的方法,如下所示:
{
wxLogNull logNull;
wxDir dir(badDir);
if ( !dir.IsOpened() )
{
return;
}
}
wxFileName
wxFileName 用来处理文件名.它可以分解和组合文件名,还提供了很多额外的操作,其中某些为静态函数.下面演示了一些例子,更多的功能请参考 wxWidgets 的手册:
#include "wx/filename.h"
// 使用字符串创建文件名
wxFileName fname(wxT("MyFile.txt"));
// Normalize,在 windows 平台上这个函数的动作包括
// 确保文件名为长文件名格式
fname.Normalize(wxPATH_NORM_LONG|wxPATH_NORM_DOTS|wxPATH_NORM_TILDE|
wxPATH_NORM_ABSOLUTE);
// 返回全路径
wxString filename = fname.GetFullPath();
// 返回相对于当前目录的路径
fname.MakeRelativeTo(wxFileName::GetCwd());
// 文件存在吗?
bool exists = fname.FileExists();
// 另外一个文件存在吗?
bool exists2 = wxFileName::FileExists(wxT("c:\\temp.txt"));
// 返回文件名的名称部分
wxString name = fname.GetName();
// 返回路径部分
wxString path = fname.GetPath();
// 在 windows 系统上返回相应的短路径文件名,其它平台上
// 返回本身.
wxString shortForm = fname.GetShortPath();
// 创建一个文件夹
bool ok = wxFileName::Mkdir(wxT("c:\\thing"));
File Functions
下表列出了一些有用的静态文件操作函数,它们定义在头文件 wx/filefn.h 中.请同时参考 wxFileName 类,尤其是其中的静态函数部分,比如 wxFileName::FileExists 函数。
wxDirExists(dir) | 是否目录存在. 参考 wxFileName::DirExists |
---|---|
wxConcatFiles(f1, f2, f3) | 将 f1 和 f2 合并为 f3, 成功时返回 True。 |
wxCopyFile(f1, f2, overwrite) | 拷贝 f1 到 f2,可选择是否覆盖已存在的 f2.返回 Bool 型 |
wxFileExists(file) | 测试是否文件存在. 参考 wxFileName::FileExists |
wxFileModificationTime(file) | 返回文件修改时间(time_t 类型). 参考 wxFileName::GetModificationTime,它返回 wxDateTime 类型 |
wxFileNameFromPath(file) | 返回文件全路径的文件名部分. 推荐使用 wxFileName::SplitPath 函数 |
wxGetCwd() | 返回当前工作目录. 参考 wxFileName::GetCwd |
wxGetdiskSpace (path, total, free) | 返回指定路径所在的磁盘的全部空间和空闲空间,空间为 wxLongLong 类型。 |
wxIsAbsolutePath(path) | 测试指定的路径是否为绝对路径。 |
wxMkdir(dir, permission=777) | 创建一个目录,其父目录必须存在,可选指定目录访问掩码.返回 bool 型 |
wxPathOnly(path) | 返回给定全路径的目录部分。 |
wxRemoveFile(file) | 删除文件,成功时返回 True。 |
wxRenameFile(file1, file2) | 重命名文件,成功时返回 True.如果需要进行文件拷贝,则直接返回 False。 |
wxRmdir(file) | 移除空目录,成功时返回 True。 |
wxSetWorkingDirectory(file) | 设置当前工作目录,返回 bool 型。 |
wxWidgets 同样提供了许多函数来封装标准 C 函数,比如: wxFopen, wxFputc 和 wxSscanf,这些函数没有在手册中记录,不过你应该可以在 include/wx/wxchar.h 中找到它们。
另外一个有用的宏是 wxFILE_SEP_PATH,它代表了不同平台上的路径分割符,比如在 windows 平台上它代表"\",而在 Unix 平台上则代表"/"。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论