// io_utils.cpp - 通用 IO 工具实现 #include "io_utils.h" #include "config.h" #include #include #include #include #include #include // stb single-header JPEG 编码器(实现仅保留在本文件,全工程只定义一次) #define STB_IMAGE_WRITE_IMPLEMENTATION #include "PAVO2_SDK/include/stb_image_write.h" #ifdef _WIN32 #include // _mkdir #include #include #include #include #else #include #include #include #include #endif std::string trim_str(const std::string& s) { size_t b = s.find_first_not_of(" \t\r\n"); if (b == std::string::npos) return ""; size_t e = s.find_last_not_of(" \t\r\n"); return s.substr(b, e - b + 1); } std::string gbk_to_utf8(const std::string& s) { #ifdef _WIN32 if (s.empty()) return s; int wlen = MultiByteToWideChar(CP_ACP, 0, s.c_str(), (int)s.size(), nullptr, 0); if (wlen <= 0) return s; std::wstring wbuf(wlen, L'\0'); MultiByteToWideChar(CP_ACP, 0, s.c_str(), (int)s.size(), &wbuf[0], wlen); int ulen = WideCharToMultiByte(CP_UTF8, 0, wbuf.c_str(), wlen, nullptr, 0, nullptr, nullptr); if (ulen <= 0) return s; std::string ubuf(ulen, '\0'); WideCharToMultiByte(CP_UTF8, 0, wbuf.c_str(), wlen, &ubuf[0], ulen, nullptr, nullptr); return ubuf; #else return s; #endif } #ifdef _WIN32 static bool mkdir_one(const std::string& path) { return _mkdir(path.c_str()) == 0 || errno == EEXIST; } #else static bool mkdir_one(const std::string& path) { return mkdir(path.c_str(), 0777) == 0 || errno == EEXIST; } #endif bool make_dirs(const std::string& path) { if (path.empty()) return false; std::string cur; size_t pos = 0; while (pos <= path.size()) { size_t slash = path.find_first_of("/\\", pos); cur += path.substr(pos, (slash == std::string::npos ? path.size() : slash) - pos); if (!cur.empty() && cur != ".") { if (!mkdir_one(cur) && errno != EEXIST) return false; } if (slash == std::string::npos) break; cur += '/'; pos = slash + 1; } return true; } std::string make_task_dir(const std::string& task_id) { std::string base = "data"; make_dirs(base); time_t rawtime = std::time(nullptr); struct tm* t = std::localtime(&rawtime); char date_buf[16], time_buf[16]; std::strftime(date_buf, sizeof(date_buf), "%Y%m%d", t); std::strftime(time_buf, sizeof(time_buf), "%H%M%S", t); std::string day_dir = base + "/" + date_buf; make_dirs(day_dir); std::string task_dir = day_dir + "/" + time_buf; if (!task_id.empty()) task_dir += "_" + task_id; else task_dir += "_"; make_dirs(task_dir); return task_dir; } // 仅 Windows 用简化目录遍历;其他平台留空实现(本程序运行于 Windows) void clean_expired_log_dirs() { if (Log_Retain_Days <= 0) return; #ifdef _WIN32 std::string base = "data"; WIN32_FIND_DATAA fd; HANDLE h = FindFirstFileA((base + "/*").c_str(), &fd); if (h == INVALID_HANDLE_VALUE) return; do { if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) continue; std::string name = fd.cFileName; if (name.size() != 8) continue; // 仅处理 YYYYMMDD bool is_num = true; for (char c : name) if (c < '0' || c > '9') { is_num = false; break; } if (!is_num) continue; time_t now = std::time(nullptr); struct tm* t = std::localtime(&now); t->tm_year = std::atoi(name.substr(0, 4).c_str()) - 1900; t->tm_mon = std::atoi(name.substr(4, 2).c_str()) - 1; t->tm_mday = std::atoi(name.substr(6, 2).c_str()); time_t dir_time = std::mktime(t); double days = std::difftime(now, dir_time) / 86400.0; if (days > Log_Retain_Days) { std::string full = base + "/" + name; // 删除目录(含子文件,Windows 下逐级删除) std::string del_cmd = "rmdir /s /q \"" + full + "\""; system(del_cmd.c_str()); std::cout << "[清理] 已删除过期日志目录: " << full << std::endl; } } while (FindNextFileA(h, &fd)); FindClose(h); #endif } void save_pcd_ascii(const std::string& filename, const std::vector& xs, const std::vector& ys, const std::vector& zs) { size_t n = xs.size(); std::ostringstream oss; oss << "# .PCD v0.7 - Point Cloud Data file format\n" << "VERSION 0.7\n" << "FIELDS x y z\n" << "SIZE 4 4 4\n" << "TYPE F F F\n" << "COUNT 1 1 1\n" << "WIDTH " << n << "\n" << "HEIGHT 1\n" << "VIEWPOINT 0 0 0 1 0 0 0\n" << "POINTS " << n << "\n" << "DATA ascii\n" << std::fixed << std::setprecision(1); for (size_t i = 0; i < n; i++) { oss << xs[i] << " " << ys[i] << " " << zs[i] << "\n"; } std::string buf = oss.str(); std::ofstream f(filename, std::ios::binary); f.write(buf.data(), (std::streamsize)buf.size()); f.close(); } bool save_jpg_gray(const std::string& filename, int width, int height, const std::vector& pixels, int quality) { std::vector rgb(width * height * 3); for (int i = 0; i < width * height; i++) { uint8_t v = pixels[i]; rgb[i * 3 + 0] = v; rgb[i * 3 + 1] = v; rgb[i * 3 + 2] = v; } int ret = stbi_write_jpg(filename.c_str(), width, height, 3, rgb.data(), quality); return ret != 0; }