1.问题
C 如何向指定路径的文件写入内容呢?
这里有几点要求:
- 如果目录不存在需要自动创建。
- 如果文件不存在需要自动创建。
- 以覆盖的方式写入内容。
2.filesystem
C 17 带来了一个新的库:filesystem。
filesystem 是一个文件系统库,前身是 boost.filesystem,用于实现跨平台的文件处理。
文件系统库 filesystem 定义在头文件<filesystem>
,命名空间为 std::filesystem。
以下是常用类:
- path 类:该类表示一个路径,对字符串(路径)进行一些处理,如路径拼接、分解、获取文件名等操作。
- directory_entry 类:功如其名,目录条目,这个类才真正接触文件。
- directory_iterator 类:获取文件系统目录中文件的迭代器容器,其元素为 directory_entry 对象,可用于遍历目录。
- recursive_directory_iterator 类:与 directory_iterator 类似,但它可以递归遍历目录及其子目录中的条目。
- file_status 类:用于获取和修改文件(或目录)的属性。
- filesystem_error 类:用于处理文件系统操作中的异常情况的异常类。
- file_type 类:表示文件的类型,包括正常文件、目录、符号链接等。它通常与std::filesystem::status()函数一起使用来获取文件的类型。
此外,还有 space_info、perms、perm_options 等类的说明,可在 cppreference.com 查看。
3.示例
下面演示利用 filesystem 实现自动创建目录与文件,并覆盖写入。
代码语言:javascript复制#include <ios>
#include <fstream>
#include <filesystem>
// 将内容以覆盖的方式写入文件,如果文件不存在,则自动创建。
void flushResult(const std::string filepath, const std::string data) {
// 获取文件所在目录的路径。
std::filesystem::path dirPath = std::filesystem::path(filepath).parent_path();
// 创建目录(如果目录不存在)。
if (!dirPath.empty()) {
if (!std::filesystem::exists(dirPath)) {
std::filesystem::create_directories(dirPath);
}
}
// 打开文件,如果文件不存在则创建。
std::ofstream outputFile(filepath, std::ios::out | std::ios::trunc);
outputFile << data;
outputFile.close();
}
在创建目录前需要判断目录 path 是否为空:
代码语言:javascript复制path::empty() // 检查路径是否为空
如果传入的文件路径只包含文件名,那么调用 filesystem::create_directories 传入空的目录 path 将引发异常。
下面在 Windows 环境测试一下。
代码语言:javascript复制int main() {
flushResult(".\dir1\dir2\lvlv.json", "{"hell":"world"}");
}
注意,Windows 目录中的反斜杠需要转义,JOSN 中的双引号也需要转义。或者使用 C 11 原生字符串。
代码语言:javascript复制int main() {
flushResult(R"(.dir1dir2lvlv.json)", R"({"hell":"world"})");
}
编译运行上面的 main() 函数,将在当前工作目录下创建.dir1di2lvlv.json
文件并写入{"hell":"world"}
。
参考文献
Filesystem library (since C 17) - cppreference.com