|
|
|
|
|
#pragma once
|
|
|
|
|
|
#include "stdafx.h"
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
#include <map>
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief TSV(Tab分隔值)数据解析器
|
|
|
|
|
|
*
|
|
|
|
|
|
* 独立的 TSV 解析工具类,可被其他模块复用
|
|
|
|
|
|
* 负责将 TSV 格式的文本数据解析为结构化的表格数据
|
|
|
|
|
|
*/
|
|
|
|
|
|
class TsvParser
|
|
|
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 表格数据结构
|
|
|
|
|
|
*
|
|
|
|
|
|
* 存储解析后的表格数据,包括列头和数据行
|
|
|
|
|
|
*/
|
|
|
|
|
|
struct TableData
|
|
|
|
|
|
{
|
|
|
|
|
|
std::vector<CString> headers; // 列头
|
|
|
|
|
|
std::vector<std::vector<CString>> rows; // 数据行
|
|
|
|
|
|
std::map<CString, int> columnIndexMap; // 列名到索引的映射(不区分大小写)
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 获取列索引
|
|
|
|
|
|
* @param columnName 列名(不区分大小写)
|
|
|
|
|
|
* @return 列索引,未找到返回 -1
|
|
|
|
|
|
*/
|
|
|
|
|
|
int GetColumnIndex(const CString& columnName) const;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 获取字段值
|
|
|
|
|
|
* @param row 行对象
|
|
|
|
|
|
* @param columnName 列名
|
|
|
|
|
|
* @return 字段值(已 Trim),未找到返回空字符串
|
|
|
|
|
|
*/
|
|
|
|
|
|
CString GetValue(const std::vector<CString>& row, const CString& columnName) const;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 获取字段值(按索引)
|
|
|
|
|
|
* @param row 行对象
|
|
|
|
|
|
* @param columnIndex 列索引
|
|
|
|
|
|
* @return 字段值(已 Trim),越界返回空字符串
|
|
|
|
|
|
*/
|
|
|
|
|
|
CString GetValue(const std::vector<CString>& row, int columnIndex) const;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 获取字段的 double 值
|
|
|
|
|
|
* @param row 行对象
|
|
|
|
|
|
* @param columnName 列名
|
|
|
|
|
|
* @param defaultValue 默认值(字段不存在或无法转换时使用)
|
|
|
|
|
|
* @return double 值
|
|
|
|
|
|
*/
|
|
|
|
|
|
double GetDoubleValue(const std::vector<CString>& row, const CString& columnName, double defaultValue = 0.0) const;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 是否为空表
|
|
|
|
|
|
*/
|
|
|
|
|
|
bool IsEmpty() const { return rows.empty(); }
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 获取数据行数
|
|
|
|
|
|
*/
|
|
|
|
|
|
size_t GetRowCount() const { return rows.size(); }
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 解析 TSV 数据
|
|
|
|
|
|
* @param tsvData TSV 格式的文本数据(第一行为列头,使用 Tab 分隔)
|
|
|
|
|
|
* @param outTableData 输出:解析后的表格数据
|
|
|
|
|
|
* @return 是否解析成功
|
|
|
|
|
|
*/
|
|
|
|
|
|
static bool Parse(const CString& tsvData, TableData& outTableData);
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 分割数据为行
|
|
|
|
|
|
* @param data 完整数据
|
|
|
|
|
|
* @param outLines 输出:行列表
|
|
|
|
|
|
*/
|
|
|
|
|
|
static void SplitLines(const CString& data, std::vector<CString>& outLines);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 解析单行 TSV 数据
|
|
|
|
|
|
* @param line 一行数据
|
|
|
|
|
|
* @param outFields 输出:字段列表
|
|
|
|
|
|
* @return 是否解析成功
|
|
|
|
|
|
*/
|
|
|
|
|
|
static bool ParseLine(const CString& line, std::vector<CString>& outFields);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 构建列名索引映射
|
|
|
|
|
|
* @param headers 列头列表
|
|
|
|
|
|
* @param outIndexMap 输出:列名到索引的映射
|
|
|
|
|
|
*/
|
|
|
|
|
|
static void BuildColumnIndexMap(const std::vector<CString>& headers,
|
|
|
|
|
|
std::map<CString, int>& outIndexMap);
|
|
|
|
|
|
};
|