#include #include #include /* ------------------------------------------------------------------------------------------------------------------ */ /* */ #ifdef _WIN32 #include typedef struct { HANDLE hFind; WIN32_FIND_DATAA findData; } WinIterCtx; #else #ifndef _FILE_OFFSET_BITS #define _FILE_OFFSET_BITS 64 #endif #include #include #include #include typedef struct { DIR* dir; } PosixIterCtx; #endif /* ------------------------------------------------------------------------------------------------------------------ */ /* */ // 内部辅助函数:获取下一个有效条目(过滤 "." 和 "..") static void c_FileIter_InternalFetch(c_FileIter_t* iter) { #ifdef _WIN32 WinIterCtx* ctx = (WinIterCtx*)iter->internal_ctx; while (FindNextFileA(ctx->hFind, &ctx->findData)) { if (strcmp(ctx->findData.cFileName, ".") == 0 || strcmp(ctx->findData.cFileName, "..") == 0) { continue; // 过滤 } // 填充缓存 strncpy(iter->current.name, ctx->findData.cFileName, sizeof(iter->current.name) - 1); iter->current.name[sizeof(iter->current.name) - 1] = '\0'; if (ctx->findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { iter->current.type = C_FILE_TYPE_DIR; iter->current.size = 0; } else { iter->current.type = C_FILE_TYPE_REGULAR; iter->current.size = ((unsigned long long)ctx->findData.nFileSizeHigh << 32) | ctx->findData.nFileSizeLow; } iter->has_next = C_TRUE; return; } #else PosixIterCtx* ctx = (PosixIterCtx*)iter->internal_ctx; struct dirent* entry; while ((entry = readdir(ctx->dir)) != NULL) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { continue; // 过滤 } // 填充名字 strncpy(iter->current.name, entry->d_name, sizeof(iter->current.name) - 1); iter->current.name[sizeof(iter->current.name) - 1] = '\0'; // 组装完整路径获取大文件大小及类型 char full_path[512]; snprintf(full_path, sizeof(full_path), "%s/%s", iter->base_path, entry->d_name); struct stat stat_buf; if (stat(full_path, &stat_buf) == 0) { iter->current.size = (unsigned long long)stat_buf.st_size; if (S_ISDIR(stat_buf.st_mode)) { iter->current.type = C_FILE_TYPE_DIR; } else if (S_ISREG(stat_buf.st_mode)) { iter->current.type = C_FILE_TYPE_REGULAR; } else { iter->current.type = C_FILE_TYPE_UNKNOWN; } } else { iter->current.type = C_FILE_TYPE_UNKNOWN; iter->current.size = 0; } iter->has_next = C_TRUE; return; } #endif // 没有更多文件了,触发自动资源清理 iter->has_next = C_FALSE; if (iter->internal_ctx) { #ifdef _WIN32 FindClose(((WinIterCtx*)iter->internal_ctx)->hFind); #else closedir(((PosixIterCtx*)iter->internal_ctx)->dir); #endif C_FREE(iter->internal_ctx); iter->internal_ctx = NULL; } } /* ------------------------------------------------------------------------------------------------------------------ */ /* */ c_err_t c_FileIter_Init(c_FileIter_t* iter, const char* dirpath) { if (!iter || !dirpath) return C_ERR_FAIL; iter->internal_ctx = NULL; iter->has_next = C_FALSE; strncpy(iter->base_path, dirpath, sizeof(iter->base_path) - 1); iter->base_path[sizeof(iter->base_path) - 1] = '\0'; #ifdef _WIN32 WinIterCtx* ctx = (WinIterCtx*)C_ALLOC(sizeof(WinIterCtx)); if (!ctx) return C_ERR_FAIL; char search_path[512]; snprintf(search_path, sizeof(search_path), "%s\\*", dirpath); ctx->hFind = FindFirstFile(search_path, &ctx->findData); if (ctx->hFind == INVALID_HANDLE_VALUE) { C_FREE(ctx); return C_ERR_FAIL; } iter->internal_ctx = ctx; // 检查第一个读取到的是否是 "." 或 "..",如果是,则继续查找有效文件 if (strcmp(ctx->findData.cFileName, ".") == 0 || strcmp(ctx->findData.cFileName, "..") == 0) { c_FileIter_InternalFetch(iter); } else { strncpy(iter->current.name, ctx->findData.cFileName, sizeof(iter->current.name) - 1); iter->current.name[sizeof(iter->current.name) - 1] = '\0'; if (ctx->findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { iter->current.type = C_FILE_TYPE_DIR; iter->current.size = 0; } else { iter->current.type = C_FILE_TYPE_REGULAR; iter->current.size = ((unsigned long long)ctx->findData.nFileSizeHigh << 32) | ctx->findData.nFileSizeLow; } iter->has_next = C_TRUE; } #else PosixIterCtx* ctx = (PosixIterCtx*)C_ALLOC(sizeof(PosixIterCtx)); if (!ctx) return C_ERR_FAIL; ctx->dir = opendir(dirpath); if (!ctx->dir) { C_FREE(ctx); return C_ERR_FAIL; } iter->internal_ctx = ctx; // 触发预读第一项 c_FileIter_InternalFetch(iter); #endif return C_ERR_OK; } c_bool_t c_FileIter_HasNext(c_FileIter_t* iter) { return (iter != NULL) ? iter->has_next : C_FALSE; } void c_FileIter_Next(c_FileIter_t* iter) { if (iter && iter->has_next) { c_FileIter_InternalFetch(iter); } } const c_FileEntry_t* c_FileIter_Get(c_FileIter_t* iter) { if (iter && iter->has_next) { return &(iter->current); } return NULL; } c_err_t c_FileIter_Remove(c_FileIter_t* iter) { if (!iter || !iter->has_next) return C_ERR_FAIL; char full_path[512]; #ifdef _WIN32 snprintf(full_path, sizeof(full_path), "%s\\%s", iter->base_path, iter->current.name); #else snprintf(full_path, sizeof(full_path), "%s/%s", iter->base_path, iter->current.name); #endif int res = -1; if (iter->current.type == C_FILE_TYPE_DIR) { #ifdef _WIN32 res = RemoveDirectory(full_path) ? 0 : -1; #else res = rmdir(full_path); #endif } else { #ifdef _WIN32 res = DeleteFile(full_path) ? 0 : -1; #else res = unlink(full_path); #endif } // 执行完物理删除后,提前释放当前迭代器的内部流句柄,防止调用者后续发生未知异常 iter->has_next = C_FALSE; if (iter->internal_ctx) { #ifdef _WIN32 FindClose(((WinIterCtx*)iter->internal_ctx)->hFind); #else closedir(((PosixIterCtx*)iter->internal_ctx)->dir); #endif C_FREE(iter->internal_ctx); iter->internal_ctx = NULL; } return (res == 0) ? C_ERR_OK : C_ERR_FAIL; }