<think>我们注意到在原始数据中,有两个主要的参数部分(Param):
1. ImageMaster - Certificate
2. Measurement Parameter: Tilt Corrected MTF @ Best/TF1
每个部分都有自己的标题(title)和一组键值对。
因此,我们需要调整解析策略,将整个文档视为多个参数部分(而不仅仅是证书部分和其他部分)。每个参数部分由一个标题和一组键值对(可能出现在段落或表格中)组成。
修改方案:
1. 在解析参数部分时,不再只解析预定义的部分,而是动态识别所有参数部分。
2. 使用一个列表来存储所有遇到的参数部分,然后根据标题映射到我们数据结构中的特定成员。
但是,我们的数据结构(tagParameterSections)是固定的,因此我们需要将每个解析出来的参数部分根据标题映射到对应的成员。
步骤:
1. 遍历文档,识别标题(通常是加粗、大字号或独立的文本块)。
2. 当遇到一个标题时,开始一个新的参数部分,直到遇到下一个标题。
3. 在标题之间的内容中提取键值对(包括段落和表格)。
由于数据结构中已经预定义了多个部分(如tagMTFvsImageHeight等),我们可以创建一个映射表,将标题字符串映射到对应的成员。
例如:
"ImageMaster - Certificate" -> 这个部分的数据应该存储在哪里?注意,我们的数据结构中没有专门为证书设置的参数部分,证书部分已经单独用tagCertificate结构存储了。
因此,我们需要重新考虑:
实际上,证书部分(ImageMaster - Certificate)已经在parseCertificateInfo中解析了,所以不应该再作为参数部分出现。
所以,参数部分应该是除证书部分以外的其他部分,如"Tilt Corrected MTF"等。
修改后的参数部分解析逻辑:
1. 跳过证书部分(因为已经解析过了)。
2. 对于其他部分,根据标题映射到tagParameterSections中的成员。
但是,原始数据中参数部分的标题是"Measurement Parameter: Tilt Corrected MTF @ Best/TF1",而我们的映射表中可能是"Tilt Corrected MTF"。
因此,我们需要一个更灵活的映射方式,比如使用包含关系(例如,标题中包含"Tilt Corrected MTF"就映射到tagTiltCorrectedMTF)。
具体调整:
1. 在parseParameterSections函数中,我们遍历文档,寻找可能是参数部分标题的文本块。
2. 当找到一个标题时,检查它是否包含我们预定义的关键字(例如,对于tagTiltCorrectedMTF,我们可能定义关键字为"Tilt Corrected MTF")。
3. 然后,将这个标题之后直到下一个标题的内容作为该参数部分的内容,从中提取键值对。
同时,由于证书部分已经单独解析,我们可以在遍历时跳过证书部分。
实现:
步骤:
a. 创建一个映射表,将关键字映射到参数成员指针。
b. 遍历文档的文本块。
c. 如果文本块是证书部分的标题,跳过(因为证书部分已经解析)。
d. 如果文本块包含某个关键字,则将其识别为参数部分标题,并设置当前活动部分。
e. 在活动部分中,提取键值对(包括表格)。
注意:一个参数部分可能包含多个段落和表格。
修改后的parseParameterSections函数:
伪代码:
QMap<QString, tagMeasurementParameter*> paramMap; // 关键字到成员的映射
QString currentKey; // 当前活动的关键字
tagMeasurementParameter* currentParam = nullptr;
for (each block) {
QString text = block.text().trimmed();
// 检查是否是证书部分标题,如果是则跳过
if (text.contains("ImageMaster - Certificate")) {
currentParam = nullptr;
continue;
}
// 检查是否是参数部分标题
if (text.startsWith("Measurement Parameter:")) {
// 提取实际部分名称,例如"Tilt Corrected MTF @ Best/TF1"
QString sectionName = text.mid(23).trimmed();
// 在映射表中查找包含的关键字
currentKey = "";
for (auto it = paramMap.begin(); it != paramMap.end(); ++it) {
if (sectionName.contains(it.key())) {
currentKey = it.key();
break;
}
}
if (!currentKey.isEmpty()) {
currentParam = paramMap[currentKey];
currentParam->title = sectionName; // 存储完整的标题
} else {
currentParam = nullptr;
}
continue;
}
// 如果当前在参数部分内,解析键值对
if (currentParam) {
// 从文本块中提取键值对
extractKeyValuePairs(text, currentParam->param);
// 检查文本块关联的表格
QTextTable* table = ...;
if (table) {
extractKeyValueTable(table, currentParam->param);
}
}
}
但是,注意:参数部分可能有多个段落,并且可能跨多个文本块。
另外,我们还需要考虑证书部分已经解析过,所以跳过整个证书部分。但是,证书部分在文档中的位置可能不固定,所以我们可以通过标题来识别。
因此,我们修改解析流程:
1. 首先,解析证书部分(使用之前的方法,因为它包含特定的字段)。
2. 然后,解析参数部分,跳过已经解析过的证书部分。
在参数部分解析中,我们只处理以"Measurement Parameter:"开头的部分。
同时,我们需要定义映射表的关键字。例如:
paramMap["MTF vs Image Height"] = ¶ms.tagMTFvsImageHeight;
paramMap["MTF vs Object Angle"] = ¶ms.tagMTFvsObjectAngle;
...
paramMap["Tilt Corrected MTF"] = ¶ms.tagTiltCorrectedMTF;
注意:原始数据中的标题可能是"Tilt Corrected MTF @ Best/TF1",但我们的关键字是"Tilt Corrected MTF",这样就能匹配。
具体代码实现:
由于时间关系,这里只给出关键部分的修改,其他部分(如图表、表格)可以类似处理。
下面修改parseParameterSections函数:</think># MHT文档解析优化方案:多参数部分处理
根据您提供的新信息,我理解到MHT文档包含多个独立的参数部分,每个部分都有自己的标题和键值对数据。以下是针对这种结构的优化解析方案:
```cpp
#include <QTextDocument>
#include <QTextTable>
#include <QTextFrame>
#include <QTextBlock>
#include <QRegularExpression>
#include <QDebug>
// 定义数据结构(根据您提供的内容)
struct tagImageMasterCertificate {
QString title;
QString company;
QString operatorName;
QDateTime dateTime;
QString sampleId;
QString measureProgram;
QString temperature;
QString measuredwith;
QString instrumentSN;
QString comments;
};
struct tagMeasurementParameter {
QString title;
QMap<QString, QString> param;
};
struct tagParameterSections {
// 使用QMap存储所有参数部分,键为标题
QMap<QString, tagMeasurementParameter> sections;
// 添加辅助方法获取特定部分
tagMeasurementParameter* getSection(const QString& title) {
if (!sections.contains(title)) {
sections[title] = tagMeasurementParameter{title, {}};
}
return §ions[title];
}
};
// 其他数据结构保持不变...
class MeasurementParser {
public:
tagMeasurement parseDocument(QTextDocument* doc, const QString& filePath) {
tagMeasurement measurement;
measurement.fileName = QFileInfo(filePath).fileName();
// 1. 解析主证书信息
parseCertificateInfo(doc, measurement.tagCertificate);
// 2. 解析所有参数部分
parseAllParameterSections(doc, measurement.tagParam);
// 3. 解析图表部分
parseGraphSections(doc, measurement.tagGraph);
// 4. 解析表格部分
parseTableSections(doc, measurement.tagTable);
return measurement;
}
private:
// 解析主证书信息
void parseCertificateInfo(QTextDocument* doc, tagImageMasterCertificate& cert) {
// 查找证书部分标题
QTextBlock certificateBlock = findSectionBlock(doc, "ImageMaster - Certificate");
if (!certificateBlock.isValid()) return;
// 解析证书内容
QTextBlock currentBlock = certificateBlock.next();
while (currentBlock.isValid()) {
QString text = currentBlock.text().trimmed();
// 检查是否到达下一个部分
if (text.startsWith("Measurement Parameter:")) break;
// 解析键值对
parseKeyValuePair(text, cert);
// 检查表格
QTextTable* table = qobject_cast<QTextTable*>(doc->objectForFormat(currentBlock.blockFormat()));
if (table) {
parseCertificateTable(table, cert);
}
currentBlock = currentBlock.next();
}
}
// 解析所有参数部分
void parseAllParameterSections(QTextDocument* doc, tagParameterSections& params) {
QTextBlock currentBlock = doc->begin();
while (currentBlock.isValid()) {
QString text = currentBlock.text().trimmed();
// 检测参数部分标题
if (text.startsWith("Measurement Parameter:")) {
QString sectionTitle = text;
tagMeasurementParameter* section = params.getSection(sectionTitle);
// 移动到内容部分
currentBlock = currentBlock.next();
// 解析该部分内容
while (currentBlock.isValid()) {
QString content = currentBlock.text().trimmed();
// 检查是否到达下一个部分
if (content.startsWith("Measurement Parameter:")) break;
// 解析键值对
extractKeyValuePairs(content, section->param);
// 检查表格
QTextTable* table = qobject_cast<QTextTable*>(doc->objectForFormat(currentBlock.blockFormat()));
if (table) {
extractKeyValueTable(table, section->param);
}
currentBlock = currentBlock.next();
}
// 处理完一个部分后继续,但不要跳过当前块
continue;
}
currentBlock = currentBlock.next();
}
}
// 解析键值对到证书结构
void parseKeyValuePair(const QString& text, tagImageMasterCertificate& cert) {
QRegularExpression re;
re.setPattern(R"(Company\s*[::]\s*(.+))");
QRegularExpressionMatch match = re.match(text);
if (match.hasMatch()) cert.company = match.captured(1).trimmed();
re.setPattern(R"(Operator\s*[::]\s*(.+))");
match = re.match(text);
if (match.hasMatch()) cert.operatorName = match.captured(1).trimmed();
re.setPattern(R"(Time/Date\s*[::]\s*(\d{2}:\d{2}:\d{2}\s+\w+\s+\d{1,2},\s+\d{4}))");
match = re.match(text);
if (match.hasMatch()) {
cert.dateTime = QDateTime::fromString(match.captured(1), "HH:mm:ss MMMM d, yyyy");
}
re.setPattern(R"(Sample ID\s*[::]\s*(\w+))");
match = re.match(text);
if (match.hasMatch()) cert.sampleId = match.captured(1).trimmed();
re.setPattern(R"(Measure Program\s*[::]\s*(.+))");
match = re.match(text);
if (match.hasMatch()) cert.measureProgram = match.captured(1).trimmed();
re.setPattern(R"(Temperature\s*[::]\s*([\d.]+)\s*°C)");
match = re.match(text);
if (match.hasMatch()) cert.temperature = match.captured(1).trimmed();
re.setPattern(R"(Measured with\s*[::]\s*(.+))");
match = re.match(text);
if (match.hasMatch()) cert.measuredwith = match.captured(1).trimmed();
re.setPattern(R"(Instrument S/N\s*[::]\s*(\w+))");
match = re.match(text);
if (match.hasMatch()) cert.instrumentSN = match.captured(1).trimmed();
re.setPattern(R"(Comments\s*[::]\s*(.+))");
match = re.match(text);
if (match.hasMatch()) cert.comments = match.captured(1).trimmed();
}
// 查找指定标题的文本块
QTextBlock findSectionBlock(QTextDocument* doc, const QString& title) {
QTextBlock block = doc->begin();
while (block.isValid()) {
if (block.text().contains(title)) {
return block;
}
block = block.next();
}
return QTextBlock();
}
// 从文本提取键值对
void extractKeyValuePairs(const QString& text, QMap<QString, QString>& params) {
QRegularExpression re(R"(([^::]+?)\s*[::]\s*([^\n]+))");
QRegularExpressionMatchIterator it = re.globalMatch(text);
while (it.hasNext()) {
QRegularExpressionMatch match = it.next();
QString key = match.captured(1).trimmed();
QString value = match.captured(2).trimmed();
// 跳过空键或空值
if (!key.isEmpty() && !value.isEmpty()) {
params[key] = value;
}
}
}
// 从表格提取键值对
void extractKeyValueTable(QTextTable* table, QMap<QString, QString>& params) {
const int rows = table->rows();
for (int row = 0; row < rows; ++row) {
if (table->columns() < 2) continue;
QString key = table->cellAt(row, 0).text().trimmed();
QString value = table->cellAt(row, 1).text().trimmed();
if (!key.isEmpty() && !value.isEmpty()) {
params[key] = value;
}
}
}
// 解析证书表格
void parseCertificateTable(QTextTable* table, tagImageMasterCertificate& cert) {
const int rows = table->rows();
const int cols = table->columns();
for (int row = 0; row < rows; ++row) {
QString key = table->cellAt(row, 0).text().trimmed();
QString value = (cols > 1) ? table->cellAt(row, 1).text().trimmed() : "";
if (key == "Company") cert.company = value;
else if (key == "Operator") cert.operatorName = value;
else if (key == "Time/Date") {
cert.dateTime = QDateTime::fromString(value, "HH:mm:ss MMMM d, yyyy");
}
else if (key == "Sample ID") cert.sampleId = value;
else if (key == "Measure Program") cert.measureProgram = value;
else if (key == "Temperature") cert.temperature = value;
else if (key == "Measured with") cert.measuredwith = value;
else if (key == "Instrument S/N") cert.instrumentSN = value;
else if (key == "Comments") cert.comments = value;
}
}
// 其他解析函数保持不变...
};
// 示例使用
void processDocument() {
// 创建文档
QTextDocument doc;
doc.setHtml("<html><body>"
"<h1>ImageMaster - Certificate</h1>"
"<p>Company: Sunex</p>"
"<p>Operator: TH</p>"
"<p>Time/Date: 19:09:56 July 04, 2025</p>"
"<p>Sample ID: 0</p>"
"<p>Measure Program: 3D Tilt Corrected Through Focus</p>"
"<p>Temperature: 20°C</p>"
"<p>Measured with: TRIOPTICS - MTF-LAB - Vers. 5.13.2</p>"
"<p>Instrument S/N: 09-113-0259</p>"
"<p>Comments: AMT5</p>"
"<h2>Measurement Parameter: Tilt Corrected MTF @ Best/TF1</h2>"
"<p>Setup Type: Object Infinite / Image Finite</p>"
"<p>EFL (Collimator): 50 mm</p>"
"<p>Wavelength: 560 nm (PE)</p>"
"<p>EFL (Sample): 1.0506 mm</p>"
"<p>F-Number: 2.0000</p>"
"<p>Focus Position: 41.6582 mm</p>"
"<p>Optimize Freq.: 100.0 lp/mm</p>"
"<p>Best Focus TF1: 41.6582 mm</p>"
"</body></html>");
// 解析文档
MeasurementParser parser;
tagMeasurement measurement = parser.parseDocument(&doc, "sample.mht");
// 输出结果
qDebug() << "Certificate Info:";
qDebug() << " Company:" << measurement.tagCertificate.company;
qDebug() << " Operator:" << measurement.tagCertificate.operatorName;
qDebug() << " Date/Time:" << measurement.tagCertificate.dateTime.toString();
qDebug() << " Measure Program:" << measurement.tagCertificate.measureProgram;
qDebug() << "\nParameter Sections:";
for (auto it = measurement.tagParam.sections.begin(); it != measurement.tagParam.sections.end(); ++it) {
qDebug() << "Section:" << it.key();
for (auto paramIt = it->param.begin(); paramIt != it->param.end(); ++paramIt) {
qDebug() << " " << paramIt.key() << ":" << paramIt.value();
}
}
}
// 调用示例
int main() {
processDocument();
return 0;
}
```
## 解决方案解析
### 1. 数据结构优化
```cpp
struct tagParameterSections {
// 使用QMap存储所有参数部分,键为标题
QMap<QString, tagMeasurementParameter> sections;
// 添加辅助方法获取特定部分
tagMeasurementParameter* getSection(const QString& title) {
if (!sections.contains(title)) {
sections[title] = tagMeasurementParameter{title, {}};
}
return §ions[title];
}
};
```
- 使用`QMap`动态存储多个参数部分
- 每个参数部分由其标题唯一标识
- `getSection()`方法确保始终返回有效的部分指针
### 2. 多部分解析流程
#### 证书部分解析
```cpp
void parseCertificateInfo(QTextDocument* doc, tagImageMasterCertificate& cert) {
// 查找证书部分标题
QTextBlock certificateBlock = findSectionBlock(doc, "ImageMaster - Certificate");
if (!certificateBlock.isValid()) return;
// 解析证书内容
QTextBlock currentBlock = certificateBlock.next();
while (currentBlock.isValid()) {
QString text = currentBlock.text().trimmed();
// 检查是否到达下一个部分
if (text.startsWith("Measurement Parameter:")) break;
// 解析键值对
parseKeyValuePair(text, cert);
// 检查表格
QTextTable* table = qobject_cast<QTextTable*>(doc->objectForFormat(currentBlock.blockFormat()));
if (table) {
parseCertificateTable(table, cert);
}
currentBlock = currentBlock.next();
}
}
```
- 精确定位"ImageMaster - Certificate"部分
- 遍历该部分的所有内容块
- 遇到下一个参数部分标题时停止解析
#### 参数部分解析
```cpp
void parseAllParameterSections(QTextDocument* doc, tagParameterSections& params) {
QTextBlock currentBlock = doc->begin();
while (currentBlock.isValid()) {
QString text = currentBlock.text().trimmed();
// 检测参数部分标题
if (text.startsWith("Measurement Parameter:")) {
QString sectionTitle = text;
tagMeasurementParameter* section = params.getSection(sectionTitle);
// 移动到内容部分
currentBlock = currentBlock.next();
// 解析该部分内容
while (currentBlock.isValid()) {
QString content = currentBlock.text().trimmed();
// 检查是否到达下一个部分
if (content.startsWith("Measurement Parameter:")) break;
// 解析键值对
extractKeyValuePairs(content, section->param);
// 检查表格
QTextTable* table = qobject_cast<QTextTable*>(doc->objectForFormat(currentBlock.blockFormat()));
if (table) {
extractKeyValueTable(table, section->param);
}
currentBlock = currentBlock.next();
}
// 处理完一个部分后继续,但不要跳过当前块
continue;
}
currentBlock = currentBlock.next();
}
}
```
- 扫描整个文档查找"Measurement Parameter:"开头的标题
- 为每个参数部分创建独立的数据结构
- 解析直到遇到下一个参数部分标题
- 支持表格和文本混合内容
### 3. 键值对解析增强
```cpp
void parseKeyValuePair(const QString& text, tagImageMasterCertificate& cert) {
QRegularExpression re;
re.setPattern(R"(Time/Date\s*[::]\s*(\d{2}:\d{2}:\d{2}\s+\w+\s+\d{1,2},\s+\d{4}))");
match = re.match(text);
if (match.hasMatch()) {
cert.dateTime = QDateTime::fromString(match.captured(1), "HH:mm:ss MMMM d, yyyy");
}
// 其他字段...
}
```
- 增强日期时间解析,支持"19:09:56 July 04, 2025"格式
- 使用更灵活的正则表达式处理中英文分隔符
- 支持带单位的数值解析(如温度"20°C")
### 4. 表格解析优化
```cpp
void extractKeyValueTable(QTextTable* table, QMap<QString, QString>& params) {
const int rows = table->rows();
for (int row = 0; row < rows; ++row) {
if (table->columns() < 2) continue;
QString key = table->cellAt(row, 0).text().trimmed();
QString value = table->cellAt(row, 1).text().trimmed();
// 处理带单位的数值
if (key.contains("Temperature") && !value.contains("°C")) {
value += "°C";
}
if (!key.isEmpty() && !value.isEmpty()) {
params[key] = value;
}
}
}
```
- 自动补充缺失的单位信息
- 处理不同列数的表格
- 跳过空行和无效数据
## 数据处理与验证
### 1. 数据完整性检查
```cpp
void validateMeasurement(tagMeasurement& measurement) {
// 检查证书部分必要字段
if (measurement.tagCertificate.company.isEmpty() ||
measurement.tagCertificate.operatorName.isEmpty() ||
!measurement.tagCertificate.dateTime.isValid()) {
qWarning() << "Certificate information is incomplete";
}
// 检查参数部分
for (auto& section : measurement.tagParam.sections) {
if (section.param.isEmpty()) {
qWarning() << "Parameter section" << section.title << "is empty";
}
// 检查关键参数
if (section.title.contains("Tilt Corrected MTF")) {
if (!section.param.contains("Focus Position") ||
!section.param.contains("Optimize Freq.")) {
qWarning() << "Missing critical parameters in" << section.title;
}
}
}
}
```
### 2. 单位标准化
```cpp
void normalizeUnits(tagMeasurement& measurement) {
// 标准化温度单位
if (!measurement.tagCertificate.temperature.contains("°C")) {
measurement.tagCertificate.temperature += "°C";
}
// 标准化参数部分单位
for (auto& section : measurement.tagParam.sections) {
for (auto it = section.param.begin(); it != section.param.end(); ++it) {
if (it.key().contains("Wavelength") && !it.value().contains("nm")) {
it.value() += " nm";
}
else if (it.key().contains("Freq.") && !it.value().contains("lp/mm")) {
it.value() += " lp/mm";
}
}
}
}
```
### 3. 数据转换工具
```cpp
class MeasurementConverter {
public:
// 将测量数据转换为JSON格式
QJsonObject toJson(const tagMeasurement& measurement) {
QJsonObject root;
// 证书部分
QJsonObject certificate;
certificate["title"] = measurement.tagCertificate.title;
certificate["company"] = measurement.tagCertificate.company;
certificate["operator"] = measurement.tagCertificate.operatorName;
certificate["dateTime"] = measurement.tagCertificate.dateTime.toString(Qt::ISODate);
// 其他字段...
root["certificate"] = certificate;
// 参数部分
QJsonObject parameters;
for (auto& section : measurement.tagParam.sections) {
QJsonObject sectionObj;
for (auto it = section.param.begin(); it != section.param.end(); ++it) {
sectionObj[it.key()] = it.value();
}
parameters[section.title] = sectionObj;
}
root["parameters"] = parameters;
return root;
}
// 从JSON导入测量数据
tagMeasurement fromJson(const QJsonObject& json) {
tagMeasurement measurement;
// 解析证书部分
QJsonObject certificate = json["certificate"].toObject();
measurement.tagCertificate.title = certificate["title"].toString();
measurement.tagCertificate.company = certificate["company"].toString();
measurement.tagCertificate.operatorName = certificate["operator"].toString();
measurement.tagCertificate.dateTime = QDateTime::fromString(
certificate["dateTime"].toString(), Qt::ISODate);
// 其他字段...
// 解析参数部分
QJsonObject parameters = json["parameters"].toObject();
for (auto it = parameters.begin(); it != parameters.end(); ++it) {
QString sectionTitle = it.key();
QJsonObject sectionObj = it.value().toObject();
tagMeasurementParameter* section = measurement.tagParam.getSection(sectionTitle);
for (auto paramIt = sectionObj.begin(); paramIt != sectionObj.end(); ++paramIt) {
section->param[paramIt.key()] = paramIt.value().toString();
}
}
return measurement;
}
};
```
## 性能优化策略
### 1. 增量解析与状态机
```cpp
class ParserStateMachine {
public:
enum State {
Start,
InCertificate,
InParameterSection,
InGraphSection,
InTableSection
};
ParserStateMachine() : currentState(Start) {}
void processBlock(const QTextBlock& block) {
QString text = block.text().trimmed();
switch (currentState) {
case Start:
if (text.contains("ImageMaster - Certificate")) {
currentState = InCertificate;
// 开始解析证书部分
}
else if (text.startsWith("Measurement Parameter:")) {
currentState = InParameterSection;
// 开始解析参数部分
}
break;
case InCertificate:
if (text.startsWith("Measurement Parameter:")) {
currentState = InParameterSection;
}
// 解析证书内容...
break;
case InParameterSection:
if (text.startsWith("Measurement Parameter:")) {
// 开始新的参数部分
}
else if (text.contains("Graph Section")) {
currentState = InGraphSection;
}
// 解析参数内容...
break;
// 其他状态处理...
}
}
private:
State currentState;
};
```
### 2. 并行处理多个部分
```cpp
void parseDocumentParallel(QTextDocument* doc, tagMeasurement& measurement) {
// 创建并行任务
QFuture<void> certificateFuture = QtConcurrent::run([&] {
parseCertificateInfo(doc, measurement.tagCertificate);
});
QFuture<void> parametersFuture = QtConcurrent::run([&] {
parseAllParameterSections(doc, measurement.tagParam);
});
QFuture<void> graphsFuture = QtConcurrent::run([&] {
parseGraphSections(doc, measurement.tagGraph);
});
QFuture<void> tablesFuture = QtConcurrent::run([&] {
parseTableSections(doc, measurement.tagTable);
});
// 等待所有任务完成
certificateFuture.waitForFinished();
parametersFuture.waitForFinished();
graphsFuture.waitForFinished();
tablesFuture.waitForFinished();
}
```
### 3. 内存映射文件处理
```cpp
class MappedDocumentParser {
public:
MappedDocumentParser(const QString& filePath) {
file.setFileName(filePath);
if (!file.open(QIODevice::ReadOnly)) {
qWarning() << "Failed to open file:" << filePath;
return;
}
mappedData = file.map(0, file.size());
if (!mappedData) {
qWarning() << "Failed to map file:" << filePath;
return;
}
}
~MappedDocumentParser() {
if (mappedData) file.unmap(mappedData);
file.close();
}
void parse(tagMeasurement& measurement) {
if (!mappedData) return;
// 直接处理内存映射数据
const char* data = static_cast<const char*>(mappedData);
qint64 size = file.size();
// 查找证书部分
const char* certStart = strstr(data, "ImageMaster - Certificate");
if (certStart) {
// 解析证书部分...
}
// 查找参数部分
const char* paramStart = data;
while ((paramStart = strstr(paramStart, "Measurement Parameter:"))) {
// 解析参数部分...
paramStart++; // 继续查找下一个
}
}
private:
QFile file;
uchar* mappedData = nullptr;
};
```