123 lines
4.0 KiB
Markdown
123 lines
4.0 KiB
Markdown
# 文件名解析器
|
||
|
||
> 所属模块:[解析器设计](./概览.md)
|
||
|
||
---
|
||
|
||
## 1. 文件名格式
|
||
|
||
**格式约定**:`TX面板-TX硬件-TX软件-RX类型-测试目的-年月日-测试次数.log`
|
||
|
||
**分隔符**:支持 `-`(短横线)和 `_`(下划线)两种分隔符,文件名解析时将同时拆分这两种字符。
|
||
|
||
> ⚠️ **注意**:字段值内部不应包含分隔符字符。例如,若 TX面板值为 `single-mold`,解析时会拆分为 `single` 和 `mold` 两个字段,导致解析失败。请确保字段值本身不含 `-` 或 `_`。
|
||
|
||
**示例**:
|
||
- 标准:`singleMold-v1.0-hex2_1-iPhone15-compatibility-20260702-1.log`(字段值无分隔符)
|
||
- 避免:`single-mold-v1.0-hex2.1-iPhone15-兼容性测试-20260702-1.log`(`single-mold` 会拆分)
|
||
|
||
**位置说明**:表格中的"位置"采用 1-based 索引(从 1 开始计数),与代码中的 0-based 数组索引对应。
|
||
|
||
---
|
||
|
||
## 2. 字段映射
|
||
|
||
| 位置 | 字段 | 对应维度表 | 示例值 |
|
||
|------|------|------------|--------|
|
||
| 1 | TxPanel | tx_panel.name | single-mold |
|
||
| 2 | TxHardware | tx_hardware.version | v1.0 |
|
||
| 3 | TxSoftware | tx_software.version | hex2.1 |
|
||
| 4 | RxType | rx_type.name | iPhone15 |
|
||
| 5 | TestPurpose | test_scenario.test_purpose | 兼容性测试 |
|
||
| 6 | TestDate | test_scenario.test_date | 20260702 |
|
||
| 7 | TestSequence | test_scenario.test_sequence | 1 |
|
||
|
||
---
|
||
|
||
## 3. 解析器实现
|
||
|
||
```csharp
|
||
// Parsers/FileNameParser.cs
|
||
using System.Globalization;
|
||
using WCTDataMiner.Services;
|
||
|
||
namespace WCTDataMiner.Parsers;
|
||
|
||
public class FileNameParser
|
||
{
|
||
private static readonly char[] Separators = { '-', '_' };
|
||
|
||
/// <summary>
|
||
/// 解析日志文件名,提取场景信息
|
||
/// </summary>
|
||
/// <param name="fileName">文件名(不含路径)</param>
|
||
/// <returns>场景信息,若格式不匹配返回 null</returns>
|
||
public ScenarioInfo? Parse(string fileName)
|
||
{
|
||
// 移除 .log 扩展名
|
||
var nameWithoutExt = Path.GetFileNameWithoutExtension(fileName);
|
||
if (string.IsNullOrEmpty(nameWithoutExt))
|
||
return null;
|
||
|
||
var parts = nameWithoutExt.Split(Separators);
|
||
if (parts.Length < 7)
|
||
return null;
|
||
|
||
// 解析日期
|
||
if (!TryParseDate(parts[5], out var testDate))
|
||
return null;
|
||
|
||
// 解析测试序号
|
||
if (!int.TryParse(parts[6], out var testSequence))
|
||
testSequence = 1;
|
||
|
||
return new ScenarioInfo(
|
||
TxPanel: parts[0],
|
||
TxHardware: parts[1],
|
||
TxSoftware: parts[2],
|
||
RxType: parts[3],
|
||
TestPurpose: parts.Length > 4 ? parts[4] : null,
|
||
TestDate: testDate,
|
||
TestSequence: testSequence
|
||
);
|
||
}
|
||
|
||
private static bool TryParseDate(string dateStr, out DateOnly date)
|
||
{
|
||
// 支持多种日期格式
|
||
var formats = new[] { "yyyyMMdd", "yyyy-MM-dd", "yyMMdd" };
|
||
return DateOnly.TryParseExact(dateStr, formats, CultureInfo.InvariantCulture, DateTimeStyles.None, out date);
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 4. 容错处理
|
||
|
||
| 场景 | 处理方式 |
|
||
|------|----------|
|
||
| 文件名为空或 null | 返回 null,ParseService 记录错误日志 |
|
||
| 文件名仅含扩展名(如 `.log`) | 返回 null |
|
||
| 文件名少于 7 个字段 | 返回 null,缺少必要字段 |
|
||
| 日期格式不匹配 | 返回 null,无法解析 test_date |
|
||
| 测试序号解析失败 | 使用默认值 1 |
|
||
| 文件名扩展名无效(非 `.log`) | 仍会解析,仅去除扩展名后尝试 |
|
||
|
||
> **说明**:由于解析器要求 `parts.Length >= 7` 才会成功返回,"测试目的缺失"不会单独发生——当字段不足时整体解析失败。若需支持可选字段,需调整解析逻辑。
|
||
|
||
---
|
||
|
||
## 5. 使用示例
|
||
|
||
```csharp
|
||
// 在 ParseService 中使用
|
||
var fileNameParser = new FileNameParser();
|
||
var scenarioInfo = fileNameParser.Parse("single-mold-v1.0-hex2.1-iPhone15-兼容性测试-20260702-1.log");
|
||
|
||
if (scenarioInfo != null)
|
||
{
|
||
var scenario = await scenarioService.GetOrCreateScenarioAsync(scenarioInfo);
|
||
// 继续解析文件内容...
|
||
}
|
||
``` |