You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

164 lines
3.5 KiB
C++

1 month ago
#include "stdafx.h"
#include "TsvParser.h"
//=============================================================================
// TableData 成员函数实现
//=============================================================================
int TsvParser::TableData::GetColumnIndex(const CString& columnName) const
{
CString key = columnName;
key.MakeUpper();
key.Trim();
auto it = columnIndexMap.find(key);
if (it != columnIndexMap.end())
return it->second;
return -1;
}
CString TsvParser::TableData::GetValue(const std::vector<CString>& row, const CString& columnName) const
{
int index = GetColumnIndex(columnName);
return GetValue(row, index);
}
CString TsvParser::TableData::GetValue(const std::vector<CString>& row, int columnIndex) const
{
if (columnIndex >= 0 && columnIndex < (int)row.size())
{
CString value = row[columnIndex];
value.Trim();
return value;
}
return _T("");
}
double TsvParser::TableData::GetDoubleValue(const std::vector<CString>& row, const CString& columnName, double defaultValue) const
{
CString strValue = GetValue(row, columnName);
if (strValue.IsEmpty())
return defaultValue;
return _tstof(strValue);
}
//=============================================================================
// TsvParser 实现
//=============================================================================
bool TsvParser::Parse(const CString& tsvData, TableData& outTableData)
{
outTableData.headers.clear();
outTableData.rows.clear();
outTableData.columnIndexMap.clear();
if (tsvData.IsEmpty())
{
TRACE("TsvParser::Parse - 数据为空\n");
return false;
}
// 分割数据为行
std::vector<CString> lines;
SplitLines(tsvData, lines);
if (lines.size() < 2)
{
TRACE("TsvParser::Parse - 数据至少需要列头和一行数据\n");
return false;
}
// 解析列头
if (!ParseLine(lines[0], outTableData.headers))
{
TRACE("TsvParser::Parse - 列头解析失败\n");
return false;
}
// 构建列名索引映射
BuildColumnIndexMap(outTableData.headers, outTableData.columnIndexMap);
// 解析数据行
for (size_t i = 1; i < lines.size(); i++)
{
std::vector<CString> fields;
if (ParseLine(lines[i], fields))
{
outTableData.rows.push_back(fields);
}
}
if (outTableData.rows.empty())
{
TRACE("TsvParser::Parse - 没有有效的数据行\n");
return false;
}
return true;
}
void TsvParser::SplitLines(const CString& data, std::vector<CString>& outLines)
{
outLines.clear();
CString line;
int pos = 0;
while (pos < data.GetLength())
{
int newlinePos = data.Find('\n', pos);
if (newlinePos == -1)
{
line = data.Mid(pos);
line.Trim();
if (!line.IsEmpty())
outLines.push_back(line);
break;
}
line = data.Mid(pos, newlinePos - pos);
line.Trim();
if (!line.IsEmpty())
outLines.push_back(line);
pos = newlinePos + 1;
}
}
bool TsvParser::ParseLine(const CString& line, std::vector<CString>& outFields)
{
outFields.clear();
if (line.IsEmpty())
return false;
CString field;
for (int i = 0; i < line.GetLength(); i++)
{
if (line[i] == '\t')
{
outFields.push_back(field);
field.Empty();
}
else
{
field += line[i];
}
}
outFields.push_back(field); // 添加最后一个字段
return !outFields.empty();
}
void TsvParser::BuildColumnIndexMap(const std::vector<CString>& headers,
std::map<CString, int>& outIndexMap)
{
outIndexMap.clear();
for (size_t i = 0; i < headers.size(); i++)
{
CString key = headers[i];
key.MakeUpper();
key.Trim();
outIndexMap[key] = (int)i;
}
}