参考文档:
https://docs.wxwidgets.org/3.2/overview_file.html
https://docs.wxwidgets.org/3.2/classwx_text_file.html
https://docs.wxwidgets.org/3.2/classwx_file.html
https://docs.wxwidgets.org/3.2/classwx_temp_file.html
https://docs.wxwidgets.org/3.2/classwx_dir.html
一、介绍
wxWidgets 提供了一些函数和类以便于文件处理,主要强调跨平台这一特性,例如通过 wxTextFile
类转换不同类型的文本文件(DOS/Unix/Mac)。wxFile
用于低级 IO,wxTempFile
设计为安全地替换文件内容,而 wxTextFile
适用于逐行处理小文本文件,wxDir
则帮助枚举目录中的文件或子目录。
二、wxTextFile 类型
(一)介绍
wxTextFile
是一个用于逐行操作文本文件的简易类。它能够识别不同平台下行结束符的差异,并能够在不破坏“非本地”行结束序列的情况下编辑文件,甚至可以用来修改文本文件中的行结束字符类型。
但是,这个类并不适用于大型文件处理,因为它会将整个文件加载到内存中。对于大于1兆字节的文件,它的处理能力会受限,不过,对于配置文件或程序源代码这样的小文件而言,这一限制不算严重。
(二)使用方法
- 创建并打开文件:使用
wxTextFile::Create()
或wxTextFile::Open()
函数,可以打开文件并读取内容到内存中,然后关闭文件。 - 处理文件中的行:可以通过直接访问函数如
wxTextFile::GetLineCount()
和wxTextFile::GetLine()
,或者使用顺序访问函数,包括wxTextFile::GetFirstLine()
、wxTextFile::GetNextLine()
及wxTextFile::GetLastLine()
和wxTextFile::GetPrevLine()
。顺序访问函数会维护当前行号。 - 添加或删除文件中的行:通过
wxTextFile::AddLine()
和wxTextFile::InsertLine()
添加新行,wxTextFile::RemoveLine()
删除现有行。wxTextFile::Clear()
可以清空文件。 - 保存更改:需要注意的是,对文件所做的更改不会自动保存。要保存更改,必须显式调用
wxTextFile::Write()
,这一步骤还可以改变行结束符类型。
(三)代码示例
#include <wx/textfile.h>
#include <wx/wxcrt.h>
int main()
{
// 使得wxWidgets使用本地化的文本(即能够输出中文)
std::locale::global(std::locale(""));
// 创建一个wxTextFile对象
wxTextFile file;
// 打开一个已存在的文件,或者创建一个新文件
wxString filePath = wxT("example1.txt");
if (!wxFileExists(filePath))
file.Create(filePath);
file.Open(filePath);
if (!file.IsOpened())
return -1; // 这句不用说了吧?
// 写入一些文本行(使用不同格式)
file.AddLine(wxT("第一行"), wxTextFileType_Dos); // DOS格式
file.AddLine(wxT("第二行"), wxTextFileType_Unix); // Unix格式
file.AddLine(wxT("第三行"), wxTextFileType_Dos); // DOS格式
// 将更改写回文件
file.Write();
file.Close();
// 再次打开文件以进行读取
if (file.Open(filePath)) {
// 遍历文件的所有行
for (wxString str = file.GetFirstLine(); !file.Eof(); str = file.GetNextLine()) {
wxPuts(str);
}
// 完成文件读取后关闭文件
file.Close();
}
return 0;
}
以下是在 Arch Linux 下使用 vim 打开“example1.txt”文件的显示效果截图:
可以看出,“第一行” 和 “第三行” 后面多出了一个 ^M
,而此时文件的显示格式为 unix
。
三、wxFile 类
(一)介绍
wxFile
是一个执行原始文件 I/O 的类。通过使用它,可以实现自动错误检查,并隐藏不同平台和编译器之间的差异。wxFile
类还会在其析构函数中自动关闭文件,以确保不会忘记关闭文件。此类是围绕 file
描述符的包装器,并提供了一组函数来进行文件操作,如打开、关闭、读取、写入和定位文件。
(二)使用方法
- 创建
wxFile
对象:可以使用默认构造函数创建对象,或通过传递文件名和打开模式来打开文件。 - 文件操作:使用
Read()
,Write()
,Seek()
等函数进行文件读写和定位操作。
下面代码创建了一个wxFile
对象,打开了名为 “myfile.txt” 的文件,并在文件中写入了一些文本:
wxFile file(wxT("myfile.txt"), wxFile::write);
if (file.IsOpened()) {
file.Write(wxT("Hi, wxFile!"));
file.Close();
}
(三)性能/效率
wxFile
设计得很小,以最小化使用它的开销,几乎没有任何开销,这有助于保持文件操作的效率。
(四)兼容性/限制
wxFile
对不同平台和编译器的差异进行了抽象,以便在不同的环境中使用。但可能不会提供一些特定平台特有的文件操作功能。
(五)示例代码
#include <wx/file.h>
#include <wx/string.h>
#include <iostream>
int main()
{
// 创建并打开文件用于写入
wxFile file(wxT("example2.txt"), wxFile::write);
if (file.IsOpened()) {
file.Write(wxT("Hello, wxFile!"));
file.Close();
}
// 重新打开文件用于读取
file.Open(wxT("example2.txt"), wxFile::read);
if (file.IsOpened()) {
wxFileOffset fileSize = file.Length();
char *buffer = new char[fileSize];
file.Read(buffer, fileSize);
std::cout << buffer << std::endl;
delete[] buffer;
// 定位到文件开头并再次读取
file.Seek(0);
buffer = new char[fileSize];
file.Read(buffer, fileSize);
std::cout << buffer << std::endl;
delete[] buffer;
file.Close();
}
return 0;
}
四、wxTempFile 类
(一)介绍
wxTempFile
是一个用于安全地替换现有文件内容的类。通过创建一个临时文件来替换原始文件,但只有在临时文件完全写入后才执行替换。如果在文件生成期间程序被中断,原始文件不会丢失。使用 wxTempFile
,可以创建一个实例,然后使用 wxFile-like
函数写入内容,最后调用 wxTempFile::Commit()
函数来替换原始文件或调用 wxTempFile::Discard()
函数来取消修改。
(二)使用方法
- 创建
wxTempFile
实例,将要替换的文件名传递给构造函数。 - 使用
wxFile-like
函数写入临时文件。 - 调用
wxTempFile::Commit()
函数确认替换原始文件,或调用wxTempFile::Discard()
函数取消修改。
(三)性能/效率
wxTempFile
类提供了一种相对安全的方法来替换文件,从而降低了因程序错误或外部中断导致的数据丢失风险。
(四)兼容性/限制
- 需要适当的文件权限来创建、写入和替换文件。
- 如果不调用
Commit()
或Discard()
,析构函数将自动调用Discard()
函数。
(五)示例代码
#include <wx/wx.h>
#include <wx/file.h>
int main()
{
wxTempFile tempFile;
// 打开文件
if (!tempFile.Open("example3.txt")) {
wxPuts("Failed to open file");
return -1;
}
// 将一些数据写入临时文件
tempFile.Write("Hello, world!", wxConvUTF8);
// 用户确认替换原始文件
wxPuts("Replace the original file? (y/n)");
char userInput;
std::cin >> userInput;
if (userInput == 'y' || userInput == 'Y') {
if (tempFile.Commit()) { // 提交修改
wxPuts("File replaced successfully");
}
else {
wxPuts("Failed to replace file");
}
}
else {
tempFile.Discard(); // 明确放弃修改(在我的 Arch Linux 下,如果“example3.txt”本不存在,则不会被创建)
wxPuts("Modifications discarded");
}
return 0;
}
五、wxDir 类
(一)介绍
wxDir
是一个用于列举目录中文件和子目录的类,它提供了一种跨平台的方式来实现 Unix 的 open
/read
/closedir
函数的功能。它主要用于遍历目录和子目录,获取目录中的文件列表。
wxDir
提供了多种函数来枚举目录中的文件和子目录,如 Traverse()
和 GetAllFiles()
函数。
(二)使用方法
- 创建
wxDir
对象,例如:wxDir dir(wxGetCwd());
。 - 检查目录是否成功打开:
dir.IsOpened()
。 - 使用
GetFirst()
函数开始枚举文件,例如:bool cont = dir.GetFirst(&filename, filespec, flags);
。 - 使用
GetNext()
函数继续枚举,例如:while (cont) { cont = dir.GetNext(&filename); }
提示:
- 使用
Traverse()
函数可以递归地枚举目录中的所有文件和子目录。 - 使用
GetAllFiles()
函数可以一次性获取目录中的所有文件列表。
(三)示例代码
# 目录结构
bin
├── sub_dir1
│ ├── file1.txt
│ ├── file2.txt
│ └── sub_sub_dir1
│ └── file3.txt
├── sub_dir2
│ └── file4.txt
├── file5.txt
└── main.exe
#include <wx/dir.h>
#include <wx/string.h>
#include <iostream>
class MyTraverser : public wxDirTraverser
{
public:
wxDirTraverseResult OnFile(const wxString &filename) override
{
std::cout << "File: " << filename.ToStdString() << std::endl;
return wxDIR_CONTINUE;
}
wxDirTraverseResult OnDir(const wxString &dirname) override
{
std::cout << "Directory: " << dirname.ToStdString() << std::endl;
return wxDIR_CONTINUE;
}
};
int main()
{
wxDir dir(wxGetCwd()); // 获取当前工作目录
if (!dir.IsOpened()) {
std::cerr << "Failed to open directory!" << std::endl;
return -1;
}
wxString filename;
bool cont = dir.GetFirst(&filename); // 获取第一个文件名
while (cont) {
std::cout << "File: " << filename.ToStdString() << std::endl;
cont = dir.GetNext(&filename); // 获取下一个文件名
}
MyTraverser traverser;
dir.Traverse(traverser); // 递归地遍历目录及其子目录
wxArrayString files;
wxDir::GetAllFiles(wxGetCwd(), &files); // 获取所有文件
for (size_t i = 0; i < files.GetCount(); ++i) {
std::cout << "File: " << files[i].ToStdString() << std::endl;
}
if (wxDir::Exists("sub_dir1")) { // 判断目录是否存在
std::cout << "sub_dir1 exists!" << std::endl;
}
return 0;
}
六、总结
wxWidgets 提供了一些文件处理相关的类和功能。wxTextFile
用于处理不同类型的文本文件,wxFile
用于低级 I/O 操作,并自动在析构函数中关闭文件。wxTempFile
设计用于安全地替换文件内容,而 wxDir
则是一个辅助类,用于枚举目录中的文件或子目录。(貌似我又照抄了第一点。。。)
【wxWidgets 教程】工具类篇:文件处理(十) 至此完毕,欢迎大家指正!感谢大家的一路支持~~