C++如何读取目录下所有文件并将Schedule结构体存入vector/std::list?
嘿,我来帮你搞定这个Schedule结构体持久化和程序重启后读取的问题!
解决方案:Schedule结构体的持久化与批量读取
一、先搞定结构体的存储(写入.txt文件)
首先你得把Schedule结构体的内容序列化成可存储的文本格式,这样才能写入.txt文件。比如假设你的结构体定义是这样的:
struct Schedule { int id; std::string taskName; std::tm startTime; bool isFinished; };
序列化时可以用一个不会和内容冲突的分隔符(比如竖线|),把每个字段拼接成一行,一个Schedule实例对应文件里的一行。
写入文件示例代码
void saveSingleSchedule(const Schedule& schedule, const std::string& filePath) { std::ofstream outFile(filePath, std::ios::app); // 用app模式追加写入,也可以覆盖写 if (!outFile.is_open()) { // 这里可以加错误处理,比如打印日志 return; } // 把tm结构体转成易存储的字符串格式,比如YYYY-MM-DD HH:MM char timeBuf[20]; std::strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M", &schedule.startTime); // 按分隔符拼接字段写入 outFile << schedule.id << "|" << schedule.taskName << "|" << timeBuf << "|" << std::boolalpha << schedule.isFinished << "\n"; }
如果要存多个Schedule,也可以遍历你的vector/list,逐个调用这个函数,或者一次性写入所有内容。
二、从单个.txt文件恢复结构体
读取就是序列化的反向操作——反序列化:把文本行拆分成字段,重新构造Schedule对象。
读取单个文件示例代码
void loadScheduleFromFile(const std::string& filePath, std::vector<Schedule>& schedules) { std::ifstream inFile(filePath); if (!inFile.is_open()) { return; } std::string line; while (std::getline(inFile, line)) { // 这里的getline是读取文件的每一行,和你之前误解的目录处理没关系 Schedule s; std::istringstream lineStream(line); std::string token; // 逐个解析字段 std::getline(lineStream, token, '|'); s.id = std::stoi(token); std::getline(lineStream, token, '|'); s.taskName = token; std::getline(lineStream, token, '|'); std::istringstream timeStream(token); timeStream >> std::get_time(&s.startTime, "%Y-%m-%d %H:%M"); std::getline(lineStream, token, '|'); s.isFinished = (token == "true"); schedules.push_back(s); } }
三、遍历指定文件夹下的所有.txt文件
你之前困惑的“用getline处理文件夹”确实不对——getline是用来读取文件内容的,遍历目录得用专门的API。推荐用C++17开始支持的std::filesystem,跨平台又方便。
遍历目录批量读取示例代码
#include <filesystem> namespace fs = std::filesystem; void loadAllSchedulesFromDir(const std::string& dirPath, std::vector<Schedule>& schedules) { // 先检查目录是否存在 if (!fs::exists(dirPath) || !fs::is_directory(dirPath)) { // 处理目录不存在的错误 return; } // 遍历目录下的所有条目 for (const auto& entry : fs::directory_iterator(dirPath)) { // 筛选出普通文件,且后缀是.txt的 if (entry.is_regular_file() && entry.path().extension() == ".txt") { loadScheduleFromFile(entry.path().string(), schedules); } } }
如果你的项目用的是C++17之前的标准,那就得用平台相关的API:Windows下用FindFirstFile/FindNextFile,Linux/macOS下用opendir/readdir/closedir。
四、一些注意事项
- 分隔符要选不会出现在结构体内容里的字符,比如如果你的任务名称可能包含逗号,就别用逗号当分隔符
- 时间的序列化和反序列化格式要完全统一,不然会解析失败
- 记得处理各种异常情况:文件打不开、内容格式错误、目录不存在等等
内容的提问来源于stack exchange,提问作者Mathieu
相关产品推荐
相关产品推荐

