#include "nmDataBinaryTools.h" // 静态成员初始化 QString nmDataBinaryTools::s_lastError = ""; // scene magic: 'NMSC' static const quint32 NM_SCENE_MAGIC = 0x4E4D5343; nmDataBinaryTools::nmDataBinaryTools() { } nmDataBinaryTools::~nmDataBinaryTools() { } // ===== 文件操作 ===== bool nmDataBinaryTools::openFileForWrite(const QString& filename, QDataStream*& stream, QFile*& file) { file = new QFile(filename); if(!file->open(QIODevice::WriteOnly)) { setLastError(QString("Cannot open file for writing: %1").arg(filename)); delete file; file = NULL; return false; } stream = new QDataStream(file); stream->setByteOrder(QDataStream::LittleEndian); stream->setVersion(QDataStream::Qt_4_8); return true; } bool nmDataBinaryTools::openFileForRead(const QString& filename, QDataStream*& stream, QFile*& file) { file = new QFile(filename); if(!file->open(QIODevice::ReadOnly)) { setLastError(QString("Cannot open file for reading: %1").arg(filename)); delete file; file = NULL; return false; } stream = new QDataStream(file); stream->setByteOrder(QDataStream::LittleEndian); stream->setVersion(QDataStream::Qt_4_8); return true; } void nmDataBinaryTools::closeFile(QDataStream*& stream, QFile*& file) { if(stream) { delete stream; stream = NULL; } if(file) { file->close(); delete file; file = NULL; } } // ===== 基础数据类型写入 ===== bool nmDataBinaryTools::writeInt(QDataStream& stream, int value) { stream << static_cast(value); return checkStreamStatus(stream); } bool nmDataBinaryTools::writeDouble(QDataStream& stream, double value) { stream << value; return checkStreamStatus(stream); } bool nmDataBinaryTools::writeString(QDataStream& stream, const QString& value) { stream << value; return checkStreamStatus(stream); } // ===== 向量写入 ===== bool nmDataBinaryTools::writeVector1D(QDataStream& stream, const std::vector& vec) { if(!writeSafeVectorSize(stream, vec.size())) return false; for(size_t i = 0; i < vec.size(); ++i) { if(!writeDouble(stream, vec[i])) return false; } return true; } bool nmDataBinaryTools::writeVector2D(QDataStream& stream, const std::vector>& vec) { if(!writeSafeVectorSize(stream, vec.size())) return false; for(size_t i = 0; i < vec.size(); ++i) { if(!writeVector1D(stream, vec[i])) return false; } return true; } bool nmDataBinaryTools::writeVector3D(QDataStream& stream, const std::vector>>& vec) { if(!writeSafeVectorSize(stream, vec.size())) return false; for(size_t i = 0; i < vec.size(); ++i) { if(!writeVector2D(stream, vec[i])) return false; } return true; } bool nmDataBinaryTools::writeVector1DInt(QDataStream& stream, const std::vector& vec) { if(!writeSafeVectorSize(stream, vec.size())) return false; for(size_t i = 0; i < vec.size(); ++i) { if(!writeInt(stream, vec[i])) return false; } return true; } bool nmDataBinaryTools::writeVector2DInt(QDataStream& stream, const std::vector>& vec) { if(!writeSafeVectorSize(stream, vec.size())) return false; for(size_t i = 0; i < vec.size(); ++i) { if(!writeVector1DInt(stream, vec[i])) return false; } return true; } bool nmDataBinaryTools::writeVector2DChunked(QDataStream& stream, const std::vector>& vec, int chunkSize) { qDebug() << "Writing large 2D vector with chunking. Size:" << (quint64)vec.size(); if(!writeSafeVectorSize(stream, vec.size())) return false; for(size_t i = 0; i < vec.size(); i += (size_t)chunkSize) { size_t endIdx = qMin(i + (size_t)chunkSize, vec.size()); for(size_t j = i; j < endIdx; ++j) { if(!writeVector1D(stream, vec[j])) return false; } if(chunkSize > 0 && (i % (size_t)(chunkSize * 10) == 0)) { qDebug() << "Chunked write progress:" << (quint64)i << "/" << (quint64)vec.size(); } } qDebug() << "Chunked write completed"; return true; } // ===== 基础数据类型读取 ===== bool nmDataBinaryTools::readInt(QDataStream& stream, int& value) { qint32 qvalue; stream >> qvalue; value = static_cast(qvalue); return checkStreamStatus(stream); } bool nmDataBinaryTools::readDouble(QDataStream& stream, double& value) { stream >> value; return checkStreamStatus(stream); } bool nmDataBinaryTools::readString(QDataStream& stream, QString& value) { stream >> value; return checkStreamStatus(stream); } // ===== 向量读取 ===== bool nmDataBinaryTools::readVector1D(QDataStream& stream, std::vector& vec) { size_t size; if(!readSafeVectorSize(stream, size)) return false; vec.resize(size); for(size_t i = 0; i < vec.size(); ++i) { if(!readDouble(stream, vec[i])) return false; } return true; } bool nmDataBinaryTools::readVector2D(QDataStream& stream, std::vector>& vec) { size_t size; if(!readSafeVectorSize(stream, size)) return false; vec.resize(size); for(size_t i = 0; i < vec.size(); ++i) { if(!readVector1D(stream, vec[i])) return false; } return true; } bool nmDataBinaryTools::readVector3D(QDataStream& stream, std::vector>>& vec) { size_t size; if(!readSafeVectorSize(stream, size)) return false; vec.resize(size); for(size_t i = 0; i < vec.size(); ++i) { if(!readVector2D(stream, vec[i])) return false; } return true; } bool nmDataBinaryTools::readVector1DInt(QDataStream& stream, std::vector& vec) { size_t size; if(!readSafeVectorSize(stream, size)) return false; vec.resize(size); for(size_t i = 0; i < vec.size(); ++i) { if(!readInt(stream, vec[i])) return false; } return true; } bool nmDataBinaryTools::readVector2DInt(QDataStream& stream, std::vector>& vec) { size_t size; if(!readSafeVectorSize(stream, size)) return false; vec.resize(size); for(size_t i = 0; i < vec.size(); ++i) { if(!readVector1DInt(stream, vec[i])) return false; } return true; } bool nmDataBinaryTools::readVector2DChunked(QDataStream& stream, std::vector>& vec, int chunkSize) { size_t size; if(!readSafeVectorSize(stream, size)) return false; qDebug() << "Reading chunked 2D vector with" << (quint64)size << "elements"; vec.resize(size); for(size_t i = 0; i < vec.size(); i += (size_t)chunkSize) { size_t endIdx = qMin(i + (size_t)chunkSize, vec.size()); for(size_t j = i; j < endIdx; ++j) { if(!readVector1D(stream, vec[j])) return false; } if(chunkSize > 0 && (i % (size_t)(chunkSize * 10) == 0)) { qDebug() << "Chunked read progress:" << (quint64)i << "/" << (quint64)vec.size(); } } qDebug() << "Chunked read completed"; return true; } // ===== 安全检查和工具方法 ===== bool nmDataBinaryTools::writeSafeVectorSize(QDataStream& stream, size_t size) { if(size > MAX_SAFE_SIZE) { setLastError(QString("Vector size too large: %1 (max: %2)") .arg((quint64)size).arg((quint64)MAX_SAFE_SIZE)); return false; } stream << static_cast(size); return checkStreamStatus(stream); } bool nmDataBinaryTools::readSafeVectorSize(QDataStream& stream, size_t& size) { quint32 qsize = 0; stream >> qsize; if(!checkStreamStatus(stream)) { setLastError("Failed to read vector size from stream"); return false; } if(qsize > MAX_SAFE_SIZE) { setLastError(QString("Vector size too large: %1 (max: %2)") .arg(qsize).arg((quint64)MAX_SAFE_SIZE)); return false; } size = static_cast(qsize); return true; } bool nmDataBinaryTools::checkStreamStatus(QDataStream& stream) { if(stream.status() != QDataStream::Ok) { switch(stream.status()) { case QDataStream::ReadPastEnd: setLastError("Stream read past end"); break; case QDataStream::ReadCorruptData: setLastError("Stream read corrupt data"); break; default: setLastError("Stream error"); break; } return false; } return true; } // ===== 错误处理 ===== QString nmDataBinaryTools::getLastError() { return s_lastError; } void nmDataBinaryTools::setLastError(const QString& error) { s_lastError = error; qDebug() << "Binary tools error:" << error; } bool nmDataBinaryTools::savePebiSceneBin(const QString& filename, const NM_PEBI_SCENE& s) { QDataStream* ds = NULL; QFile* file = NULL; if(!openFileForWrite(filename, ds, file)) return false; // Magic + Version (*ds) << static_cast(0x4E4D5343); // 'NMSC' if(!writeInt(*ds, s.version)) { closeFile(ds,file); return false; } // ===== 网格基础数据 ===== if(!writeInt(*ds, s.D)) { closeFile(ds,file); return false; } if(!writeDouble(*ds, s.GridControl)) { closeFile(ds,file); return false; } // 几何数据 if(!writeVector2D(*ds, s.Boundary)) { closeFile(ds,file); return false; } if(!writeVector2D(*ds, s.VerticalWell)) { closeFile(ds,file); return false; } if(!writeVector2D(*ds, s.HorizontalWell)) { closeFile(ds,file); return false; } if(!writeVector2D(*ds, s.FractureVerticalWell)) { closeFile(ds,file); return false; } if(!writeVector3D(*ds, s.MultistageFracturedHorizontalWell)) { closeFile(ds,file); return false; } if(!writeVector2D(*ds, s.InclinedWell)) { closeFile(ds,file); return false; } if(!writeVector2D(*ds, s.Fault)) { closeFile(ds,file); return false; } // 井顺序 if(!writeSafeVectorSize(*ds, s.wellType.size())) { closeFile(ds,file); return false; } for(size_t i=0; i> magic; if(!checkStreamStatus(*ds) || magic != 0x4E4D5343) { setLastError("Scene magic mismatch or corrupt file."); closeFile(ds,file); return false; } if(!readInt(*ds, s.version)) { closeFile(ds,file); return false; } // ===== 网格基础数据 ===== if(!readInt(*ds, s.D)) { closeFile(ds,file); return false; } if(!readDouble(*ds, s.GridControl)) { closeFile(ds,file); return false; } // 几何数据 if(!readVector2D(*ds, s.Boundary)) { closeFile(ds,file); return false; } if(!readVector2D(*ds, s.VerticalWell)) { closeFile(ds,file); return false; } if(!readVector2D(*ds, s.HorizontalWell)) { closeFile(ds,file); return false; } if(!readVector2D(*ds, s.FractureVerticalWell)) { closeFile(ds,file); return false; } if(!readVector3D(*ds, s.MultistageFracturedHorizontalWell)) { closeFile(ds,file); return false; } if(!readVector2D(*ds, s.InclinedWell)) { closeFile(ds,file); return false; } if(!readVector2D(*ds, s.Fault)) { closeFile(ds,file); return false; } // 井顺序 size_t nType = 0; if(!readSafeVectorSize(*ds, nType)) { closeFile(ds,file); return false; } s.wellType.resize(nType); for(size_t i=0; i