8.8 KiB
数据格式处理
**本文档引用的文件** - [Markup.cpp](file://cpp/Tools/Markup.cpp) - [OperTxtFile.cpp](file://cpp/Tools/OperTxtFile.cpp) - [OperUrfFile.cpp](file://cpp/Tools/OperUrfFile.cpp) - [Res3DDatFile.cpp](file://cpp/Tools/Res3DDatFile.cpp) - [Res3DDatFileRecord.cpp](file://cpp/Tools/Res3DDatFileRecord.cpp)目录
引言
Geomative Studio项目涉及多种数据格式的处理,包括用于配置的XML文件、用于测量数据交换的文本文件、专有的URF数据格式以及用于存储三维测量结果的二进制DAT文件。本文件详细阐述了Markup.cpp、OperTxtFile.cpp、OperUrfFile.cpp和Res3DDatFile.cpp四个核心模块的实现逻辑,分析其在项目缓存、任务脚本导出和结果文件生成中的应用,并讨论其性能优化与错误处理策略。
XML配置文件解析与生成
Markup.cpp模块提供了一个功能完整的XML文档解析与生成器,其核心是CMarkup类。该模块实现了对XML配置文件的节点遍历、属性读取、嵌套结构处理和内存管理。
节点遍历与属性读取
该模块通过维护一个ElemPos(元素位置)结构数组来高效地表示XML文档的树形结构。每个ElemPos结构记录了节点在文档字符串中的起始位置、长度、标签长度、层级深度以及与其他节点的父子、兄弟关系。这种设计避免了在解析时进行昂贵的字符串分割操作,而是通过索引直接定位节点内容。
对于属性读取,模块提供了SetAttrib和GetAttrib等方法。当需要设置属性时,它会计算属性在标签字符串中的精确位置,并使用x_StrInsertReplace函数进行原地插入或替换,从而最小化内存拷贝开销。
嵌套结构处理
模块通过iElemParent、iElemChild和iElemNext等指针在ElemPos结构中构建了完整的树形关系。这使得FindElem、IntoElem和OutOfElem等方法能够高效地在嵌套的XML结构中进行导航。例如,IntoElem会将当前上下文移动到当前元素的第一个子元素,而OutOfElem则会返回到父元素。
内存管理策略
内存管理是该模块的核心优势。它采用了一种“分段数组”(Segmented Array)的策略来管理ElemPos结构。ElemPosTree类将ElemPos对象存储在多个连续的内存块(段)中,而不是一个巨大的连续数组。这避免了在文档变大时重新分配和复制整个数组的性能瓶颈。GrowElemPosTree方法在需要时动态增加新的内存段,确保了在处理大型XML文件时的内存效率和性能稳定性。
节段来源
文本测量数据读写
OperTxtFile.cpp模块负责处理以文本格式存储的测量数据,支持多种编码和分隔符,主要用于任务脚本和配置的导出。
读写实现
该模块通过标准C库的fopen、fwrite和fclose函数进行文件操作。OpenFileforWrite方法以写入模式打开文件,WriteFileContent方法则负责将CStringArray中的内容写入文件。
编码与分隔符支持
虽然代码中未显式处理编码转换,但通过使用CString类,模块天然支持Unicode(UTF-16)和多字节字符集(MBCS)。文件的最终编码取决于系统区域设置和fopen函数的内部行为。对于分隔符,该模块采用了一种独特的“固定宽度”格式。SetParamWidth方法设置每个字段的固定宽度(默认18个字符),WriteFileContent方法会用空格填充不足的字段,从而形成类似表格的对齐效果。这虽然不是传统的逗号或制表符分隔,但提供了一种简单、可读性强的数据格式。
节段来源
URF专有数据格式解析
OperUrfFile.cpp模块专门用于解析和生成URF(Universal Resistivity File)专有数据格式,这是一种用于地球物理电阻率测量的行业标准文本格式。
解析规则
URF文件采用纯文本格式,包含注释行、元数据行和数据行。该模块的解析规则主要体现在WriteUrfPoleInfo和WriteUrfPoleInfo_3D等方法中:
- 头部信息:通过
WriteUrfHeadInfo和Write3DUrfHeadInfo写入文件描述和单位信息。 - 几何信息:以
:Geometry为分隔符,后跟ID,X,Y,Z的列标题,然后是电极的坐标数据。电极坐标的生成逻辑(如温纳装置、偶极装置等)由WriteElecByAR系列方法根据不同的测量阵列(AR)类型实现。 - 测量信息:以
:Measurements为分隔符,后跟A, B, M, N, V/I(ohm), I(mA), Error(%), Chargeability(mV/V)的列标题,然后是实际的测量数据。
该模块通过WriteElecByCrossHoleGeomative等方法从数据库(如TTaskBindElecInfo表)中查询电极坐标,实现了URF文件与项目数据的动态绑定。
节段来源
三维测量结果数据存储
Res3DDatFile.cpp模块负责将三维测量结果以结构化的二进制布局存储到.dat文件中,该文件用于后续的数据处理和成像。
结构化存储机制
二进制布局
该模块使用Windows API的CreateFile和WriteFile函数直接写入二进制数据。文件布局分为三个部分:
- 头部:包含标题、网格列数、行数、列间距、行间距、介质类型和记录点总数。所有数据均以ASCII文本形式写入,每项后跟换行符。
- 记录数据:包含多个测量记录。每个记录由A、B、M、N四个电极的坐标(X, Y)和电阻率值
R0组成。坐标和R0均以固定格式的文本写入。 - 尾部:写入5个零值,作为文件结束的标记。
元数据嵌入
元数据(如标题、网格尺寸、间距、介质类型)在文件头部以明文形式嵌入。SetTitle、SetGriding、SetSpacing和SetMedium等方法用于设置这些元数据。
版本兼容性处理
代码中通过VAL_ZERO、VAL_MINUS_ONE等常量定义了默认值和无效值,这有助于在不同版本的软件之间保持一定的兼容性。例如,当电极ID为-1时,表示该电极未使用。然而,代码中未发现显式的版本号字段或复杂的向后/向前兼容性逻辑,其兼容性主要依赖于固定的文件结构和数据类型。
节段来源
应用实例
上述数据格式处理模块在Geomative Studio中有着广泛的应用:
- 项目缓存:
Markup.cpp用于读写CACHE目录下的project.xml和testzone.xml文件,保存和恢复项目状态。 - 任务脚本导出:
OperTxtFile.cpp用于生成.map和.rul等脚本文件,OperUrfFile.cpp用于将任务导出为标准的URF格式,便于与其他软件交换数据。 - 结果文件生成:
Res3DDatFile.cpp用于将三维测量结果生成.dat文件,供后续的反演和成像模块使用。
性能优化与错误容忍策略
性能优化
- 内存效率:
Markup.cpp的分段数组设计避免了大文件解析时的内存抖动。 - I/O效率:
Res3DDatFile.cpp和OperUrfFile.cpp都使用了fflush来控制缓冲区刷新,平衡了性能和数据安全性。 - 算法优化:
Markup.cpp中的x_Hash函数使用了简单的加法哈希,确保了在编码查找时的快速响应。
错误容忍策略
- 输入验证:所有模块在关键操作前都进行了严格的输入验证,例如检查文件指针是否为空、参数是否在有效范围内。
- 异常处理:通过
GetLastError()获取系统错误码,并使用AfxMessageBox或MessageBoxEx向用户报告详细的错误信息(支持中英文)。 - 资源清理:在析构函数和
CloseFile方法中确保文件句柄被正确关闭,防止资源泄漏。
结论
Geomative Studio的数据格式处理体系结构清晰,各模块职责分明。Markup.cpp提供了一个高效、内存友好的XML处理方案;OperTxtFile.cpp和OperUrfFile.cpp分别处理通用文本和行业标准格式;Res3DDatFile.cpp则实现了专有的二进制结果存储。这些模块共同支撑了项目的配置管理、数据交换和结果保存功能。尽管在编码转换和版本兼容性方面有进一步提升的空间,但其整体设计稳健,错误处理完善,为地球物理测量软件的可靠运行提供了坚实的基础。