#include "WindDataFileOperator.h" #include #include #include #include #include /* * 风场数据格式说明 * 'LAMPWINDDASASET', Height , Width , TIMENUM ,// : int64_t * 'GEOTRANSFORMER',ESPGCODE,T1,T2,T3,T4,T5,T6 * "WINUV" , TIMELB, UArr[HxWxN],Varr[HxWxN] // double */ #define LAMP_WIND_SIGNAL_NUM 15 #define LAMP_WIND_GEOTRANSFORMER_NUM 14 #define LAMP_WIND_WINUV_NUM 6 LAMPWindDataDLL DataFileInfo getDataFileInfo(const char* filepath) { DataFileInfo info = { 0 }; info.Height=-1; info.Width = -1; info.Num = -1; info.firstTimestamp = -1; info.lastTimestamp = -1; info.minLon=-1; info.maxLon=-1; info.minLat=-1; info.maxLat=-1; info.ESPGCODE = -1; info.T11=-1; info.T12=-1; info.T13=-1; info.T21=-1; info.T22=-1; info.T23=-1; info.fileSize = -1; std::ifstream file(filepath, std::ios::binary); if (!file.is_open()) { std::cerr << "无法打开文件: " << filepath << std::endl; return info; } // 获取文件大小 file.seekg(0, std::ios::end); info.fileSize = file.tellg(); file.seekg(0, std::ios::beg); const char Fileheader[LAMP_WIND_SIGNAL_NUM]={ 0x4C, 0x41, 0x4D ,0x50, 0x57, 0x49, 0x4E, 0x44, 0x44 ,0x41, 0x53 ,0x41 ,0x53, 0x45 ,0x54 }; // LAMPWINDDASASET const char GeoTransHeader[LAMP_WIND_GEOTRANSFORMER_NUM] = { 0x47 ,0x45 ,0x4F ,0x54 ,0x52 ,0x41 ,0x4E ,0x53 ,0x46 ,0x4F ,0x52 ,0x4D ,0x45 ,0x52 }; // GEOTRANSFORMER const char WindUVHeader[LAMP_WIND_WINUV_NUM] = { 0x57 ,0x49 ,0x4E ,0x44 ,0x55 ,0x56 }; // WINDUV char labelchar = '\0'; for (int64_t i = 0; i < LAMP_WIND_SIGNAL_NUM; i++) { // 处理头文件 file.read(reinterpret_cast(&labelchar), 1); if (labelchar != Fileheader[i]) { file.close(); return info; } } // 读取基本维度信息 file.read(reinterpret_cast(&info.Height), sizeof(int64_t)); // H file.read(reinterpret_cast(&info.Width), sizeof(int64_t)); // W file.read(reinterpret_cast(&info.Num), sizeof(int64_t)); // N if (info.Num == 0 || info.Height == 0 || info.Width == 0) { file.close(); return info; } // 读取地理变换参数 for (int64_t i = 0; i < LAMP_WIND_GEOTRANSFORMER_NUM; i++) { // 读取标识 file.read(reinterpret_cast(&labelchar), 1); if (labelchar != GeoTransHeader[i]) { file.close(); return info; } } // 读取数据 file.read(reinterpret_cast(&info.ESPGCODE), sizeof(int64_t)); file.read(reinterpret_cast(&info.T11), sizeof(double)); file.read(reinterpret_cast(&info.T12), sizeof(double)); file.read(reinterpret_cast(&info.T13), sizeof(double)); file.read(reinterpret_cast(&info.T21), sizeof(double)); file.read(reinterpret_cast(&info.T22), sizeof(double)); file.read(reinterpret_cast(&info.T23), sizeof(double)); // 计算经纬度范围(根据地理变换参数估算) info.minLon = info.T11; info.maxLon = info.T11 + info.Width * info.T12; info.minLat = info.T21 + info.Height * info.T23; info.maxLat = info.T21; // 从数据中抽取 for (int64_t i = 0; i < LAMP_WIND_WINUV_NUM; i++) { file.read(reinterpret_cast(&labelchar), 1); if (labelchar != WindUVHeader[i]) { file.close(); return info; } } std::vector timeArr(info.Num); for (int64_t t = 0; t < info.Num; t++) { file.read(reinterpret_cast(&timeArr[t]), sizeof(int64_t)); int64_t datalen = int64_t(info.Height) * int64_t(info.Width) * 2 * sizeof(double); file.seekg(datalen, std::ios::cur); if (file.eof()) { if (t == info.Num - 1) { // 所有的数据都被处理 break; } else { file.close(); return info; } } else {} } std::vector::iterator minIter = std::min_element(timeArr.begin(),timeArr.end()); std::vector::iterator maxIter = std::max_element(timeArr.begin(),timeArr.end()); info.firstTimestamp = *minIter; info.lastTimestamp = *maxIter; file.close(); return info; } LAMPWindDataDLL int32_t get_WindDataFileTimeArr(const char* filepath, DataFileInfo info, int64_t* outtimeArr) { if (info.Num <= 0 || outtimeArr == nullptr) { return -1; } std::ifstream file(filepath, std::ios::binary); if (!file.is_open()) { return -2; } int64_t offset = LAMP_WIND_SIGNAL_NUM // LAMPWINDDASASET + 3 * sizeof(int64_t) + LAMP_WIND_GEOTRANSFORMER_NUM // GEOTRANSFORMER + sizeof(int64_t) + sizeof(double) * 6 + LAMP_WIND_WINUV_NUM; // WINUV file.seekg(offset, std::ios::beg); for (int64_t t = 0; t < info.Num; t++) { file.read(reinterpret_cast(&outtimeArr[t]), sizeof(int64_t)); int64_t datalen = int64_t(info.Height) * int64_t(info.Width) * 2 * sizeof(double); file.seekg(datalen, std::ios::cur); if (file.eof()) { if (t == info.Num - 1) { // 所有的数据都被处理 break; } else { file.close(); return -1; } } else {} } file.close(); return 0; } LAMPWindDataDLL int32_t Read_WindDataFile(const char* filepath, DataFileInfo info, int32_t timeID, double* UArr, double* VArr) { if (timeID < 0 || timeID >= info.Num || UArr == nullptr || VArr == nullptr) { return -1; } std::ifstream file(filepath, std::ios::binary); if (!file.is_open()) { return -2; } // 判断信息 file.seekg(0, std::ios::end); int64_t fileSize = file.tellg(); file.seekg(0, std::ios::beg); if (fileSize != info.fileSize) { file.close(); return -3; } int64_t Headeroffset = LAMP_WIND_SIGNAL_NUM // LAMPWINDDASASET + 3 * sizeof(int64_t) + LAMP_WIND_GEOTRANSFORMER_NUM // GEOTRANSFORMER + sizeof(int64_t) + sizeof(double) * 6 + LAMP_WIND_WINUV_NUM; // WINUV int64_t U_block_len= int64_t(info.Height) * int64_t(info.Width)* sizeof(double); int64_t V_block_len= int64_t(info.Height) * int64_t(info.Width)* sizeof(double); int64_t datalen = sizeof(int64_t) // Time + U_block_len + V_block_len; int64_t dataOffset = timeID * datalen; int64_t sumOffset = Headeroffset + dataOffset; if(sumOffset+datalen<=fileSize){} else { file.close(); return -4; } file.seekg(sumOffset, std::ios::beg); int64_t timeInt = 0; file.read(reinterpret_cast(&timeInt), sizeof(int64_t)); file.read(reinterpret_cast(UArr), U_block_len); file.read(reinterpret_cast(VArr), V_block_len); file.close(); return 0; } LAMPWindDataDLL int32_t Write_WindDataFile(const char* filepath, DataFileInfo info, int64_t timeInt,int32_t timeID, double* UArr, double* VArr) { const char Fileheader[LAMP_WIND_SIGNAL_NUM] = { 0x4C, 0x41, 0x4D ,0x50, 0x57, 0x49, 0x4E, 0x44, 0x44 ,0x41, 0x53 ,0x41 ,0x53, 0x45 ,0x54 }; // LAMPWINDDASASET const char GeoTransHeader[LAMP_WIND_GEOTRANSFORMER_NUM] = { 0x47 ,0x45 ,0x4F ,0x54 ,0x52 ,0x41 ,0x4E ,0x53 ,0x46 ,0x4F ,0x52 ,0x4D ,0x45 ,0x52 }; // GEOTRANSFORMER const char WindUVHeader[LAMP_WIND_WINUV_NUM] = { 0x57 ,0x49 ,0x4E ,0x44 ,0x55 ,0x56 }; // WINDUV if (timeID < 0 || timeID >= info.Num || UArr == nullptr || VArr == nullptr) { return -1; } // 判断文件是否存在 if (! std::filesystem::exists(filepath)) { // 文件不存在 std::fstream file(filepath, std::ios::binary | std::ios::in | std::ios::out); if (!file.is_open()) { // 如果文件不存在,创建新文件并写入完整结构 file.open(filepath, std::ios::binary | std::ios::out); if (!file.is_open()) { return -2; } // 写入文件头 for (int64_t i = 0; i < LAMP_WIND_SIGNAL_NUM; i++) { file.write(reinterpret_cast(&Fileheader[i]), sizeof(char)); } // 写入文件信息 file.write(reinterpret_cast(&info.Height), sizeof(int64_t)); // H file.write(reinterpret_cast(&info.Width), sizeof(int64_t)); // W file.write(reinterpret_cast(&info.Num), sizeof(int64_t)); // N // 写入地理变换参数 for (int64_t i = 0; i < LAMP_WIND_GEOTRANSFORMER_NUM; i++) { file.write(reinterpret_cast(&GeoTransHeader[i]), sizeof(char)); } file.write(reinterpret_cast(&info.ESPGCODE), sizeof(int64_t)); file.write(reinterpret_cast(&info.T11), sizeof(double)); file.write(reinterpret_cast(&info.T12), sizeof(double)); file.write(reinterpret_cast(&info.T13), sizeof(double)); file.write(reinterpret_cast(&info.T21), sizeof(double)); file.write(reinterpret_cast(&info.T22), sizeof(double)); file.write(reinterpret_cast(&info.T23), sizeof(double)); // 写入风场数据标签 for (int64_t i = 0; i < LAMP_WIND_WINUV_NUM; i++) { file.write(reinterpret_cast(&WindUVHeader[i]), sizeof(char)); } // 写入风场块 std::vector blockData(info.Width); for (int64_t i = 0; i < info.Width; i++) { blockData[i] = 0; } for (int64_t tid = 0; tid < info.Num; tid++) { int64_t timeValue = 0; if (tid == timeID) { // timeValue = timeInt; file.write(reinterpret_cast(&timeValue), sizeof(int64_t)); file.write(reinterpret_cast(UArr), info.Height*info.Width * sizeof(double)); file.write(reinterpret_cast(VArr), info.Height*info.Width * sizeof(double)); timeValue = 0; } else { file.write(reinterpret_cast(&timeValue), sizeof(int64_t)); for (int64_t i = 0; i < info.Height; i++) { // U file.write(reinterpret_cast(blockData.data()), info.Width*sizeof(double)); } for (int64_t i = 0; i < info.Height; i++) { // V file.write(reinterpret_cast(blockData.data()), info.Width*sizeof(double)); } } } file.close(); } } else { std::fstream file(filepath, std::ios::binary | std::ios::in | std::ios::out); // 计算数据维度 int64_t Headeroffset = LAMP_WIND_SIGNAL_NUM // LAMPWINDDASASET + 3 * sizeof(int64_t) + LAMP_WIND_GEOTRANSFORMER_NUM // GEOTRANSFORMER + sizeof(int64_t) + sizeof(double) * 6 + LAMP_WIND_WINUV_NUM; // WINUV file.seekp(LAMP_WIND_SIGNAL_NUM, std::ios::beg); int64_t height = 0; int64_t width = 0; int64_t num = 0; file.read(reinterpret_cast(&height), sizeof(int64_t)); file.read(reinterpret_cast(&width), sizeof(int64_t)); file.read(reinterpret_cast(&num), sizeof(int64_t)); if (info.Width != width || info.Height != height||info.Num num) { // 修改长度 int64_t offset = LAMP_WIND_SIGNAL_NUM +2 * sizeof(int64_t); file.seekg(offset, std::ios::beg); file.write(reinterpret_cast(&info.Num), sizeof(int64_t)); // 修改长度 offset = LAMP_WIND_SIGNAL_NUM // LAMPWINDDASASET + 3 * sizeof(int64_t) + LAMP_WIND_GEOTRANSFORMER_NUM // GEOTRANSFORMER + sizeof(int64_t) + sizeof(double) * 6 + LAMP_WIND_WINUV_NUM + int64_t(sizeof(int64_t) + int64_t(info.Width) * int64_t(info.Height) * sizeof(double) * 2) * num; file.seekg(offset, std::ios::beg);// 移动到 [n-1] >>|<<[n] 块 // 结果补零 std::vector blockData(info.Width); for (int64_t i = 0; i < info.Width; i++) { blockData[i] = 0; } for (int64_t tid = num; tid < info.Num; tid++) { int64_t timeValue = 0; if (tid == timeID) { // timeValue = timeInt; file.write(reinterpret_cast(&timeValue), sizeof(int64_t)); file.write(reinterpret_cast(UArr), info.Height * info.Width * sizeof(double)); file.write(reinterpret_cast(VArr), info.Height * info.Width * sizeof(double)); timeValue = 0; } else { file.write(reinterpret_cast(&timeValue), sizeof(int64_t)); for (int64_t i = 0; i < info.Height; i++) { // U file.write(reinterpret_cast(blockData.data()), info.Width * sizeof(double)); } for (int64_t i = 0; i < info.Height; i++) { // V file.write(reinterpret_cast(blockData.data()), info.Width * sizeof(double)); } } } } else {} // 移动到制定为 int64_t writeoffset = LAMP_WIND_SIGNAL_NUM // LAMPWINDDASASET + 3 * sizeof(int64_t) + LAMP_WIND_GEOTRANSFORMER_NUM // GEOTRANSFORMER + sizeof(int64_t) + sizeof(double) * 6 + LAMP_WIND_WINUV_NUM + int64_t(sizeof(int64_t) + int64_t(info.Width) * int64_t(info.Height) * sizeof(double) * 2) * timeID; file.seekg(writeoffset, std::ios::beg); file.write(reinterpret_cast(&timeInt), sizeof(int64_t)); file.write(reinterpret_cast(UArr), int64_t(info.Width)* int64_t(info.Height) * sizeof(double)); file.write(reinterpret_cast(VArr), int64_t(info.Width)* int64_t(info.Height) * sizeof(double)); file.close(); } return 0; }