# 编码处理流程
本文档描述 Apq.Cfg 库在读取和写入配置文件时的完整编码处理流程。
Apq.Cfg 提供了灵活的编码处理机制,支持:
| 类名 | 职责 |
|---|---|
EncodingDetector |
编码检测器,管理映射规则和缓存 |
EncodingMappingConfig |
编码映射配置,存储读取/写入规则 |
EncodingMappingRule |
单条映射规则 |
EncodingOptions |
单个配置源的编码选项 |
FileCfgSourceBase |
文件配置源基类,调用编码检测和写入 |
读取文件
│
▼
┌─────────────────────────────────────┐
│ 1. 检查 EncodingOptions.ReadStrategy │
│ 是否为 Specified? │
└─────────────────────────────────────┘
│ 是 │ 否
▼ ▼
┌─────────────┐ ┌─────────────────────────┐
│ 返回指定编码 │ │ 2. 检查读取映射配置 │
└─────────────┘ │ (MappingConfig) │
└─────────────────────────┘
│ 匹配 │ 不匹配
▼ │
┌─────────────────────┐ │
│ 3. 验证映射编码 │ │
│ 能否正确读取文件 │ │
└─────────────────────┘ │
│ 成功 │ 失败 │
▼ └────┬────┘
┌─────────────┐ │
│ 返回映射编码 │ │
└─────────────┘ │
▼
┌─────────────────────┐
│ 4. 检查缓存 │
│ (如果启用) │
└─────────────────────┘
│ 命中 │ 未命中
▼ ▼
┌─────────────┐ ┌─────────────────┐
│ 返回缓存结果 │ │ 5. BOM 检测 │
└─────────────┘ └─────────────────┘
│ 有 BOM │ 无 BOM
▼ ▼
┌───────────┐ ┌─────────────────┐
│ 返回 BOM │ │ 6. UTF.Unknown │
│ 对应编码 │ │ 库检测 │
└───────────┘ └─────────────────┘
│ 置信度 ≥ 阈值 │ < 阈值
▼ ▼
┌─────────────┐ ┌─────────────┐
│ 返回检测编码 │ │ 返回回退编码 │
└─────────────┘ │ (默认 UTF-8) │
└─────────────┘
FileCfgSourceBase.DetectEncodingEnhanced(path)EncodingDetector.Detect(path, options)EncodingOptions.GetReadEncoding(detectedEncoding)映射规则按优先级降序排列,返回第一个匹配的规则:
| 匹配类型 | 默认优先级 | 说明 |
|---|---|---|
| ExactPath | 100 | 完整路径精确匹配 |
| Wildcard | 0 | 通配符匹配 |
| Regex | 0 | 正则表达式匹配 |
| 内置 PowerShell | -100 | *.ps1, *.psm1, *.psd1 |
当读取映射匹配成功后,系统会验证该编码是否能正确读取文件:
DecoderFallback.ExceptionFallback 尝试解码文件前 4KB这确保了即使配置了错误的编码映射,系统也能自动回退到正确的编码检测。
支持的 BOM 类型:
| BOM 字节 | 编码 |
|---|---|
EF BB BF |
UTF-8 |
FF FE |
UTF-16 LE |
FE FF |
UTF-16 BE |
FF FE 00 00 |
UTF-32 LE |
00 00 FE FF |
UTF-32 BE |
写入文件
│
▼
┌─────────────────────────────────────────┐
│ 1. 检查 EncodingOptions.WriteStrategy │
└─────────────────────────────────────────┘
│
├─── Utf8NoBom ──────► 返回 UTF-8 无 BOM
│
├─── Utf8WithBom ────► 返回 UTF-8 带 BOM
│
├─── Specified ──────► 返回 EncodingOptions.WriteEncoding
│
└─── Preserve ───────┐
▼
┌─────────────────────────┐
│ 2. 检查已检测的原编码 │
│ (_detectedEncoding) │
└─────────────────────────┘
│ 有 │ 无
▼ ▼
┌─────────────┐ ┌─────────────────────┐
│ 返回原编码 │ │ 3. 检查写入映射配置 │
└─────────────┘ │ (MappingConfig) │
└─────────────────────┘
│ 匹配 │ 不匹配
▼ ▼
┌─────────────┐ ┌─────────────────┐
│ 返回映射编码 │ │ 返回 UTF-8 无 BOM │
└─────────────┘ │ (默认) │
└─────────────────┘
FileCfgSourceBase.GetWriteEncoding()EncodingOptions.WriteStrategy 分支EncodingDetector.GetWriteEncoding(path)| 策略 | 说明 |
|---|---|
Utf8NoBom |
统一转换为 UTF-8 无 BOM(默认) |
Utf8WithBom |
统一转换为 UTF-8 带 BOM |
Preserve |
保持原文件编码 |
Specified |
使用指定的编码 |
// 默认配置:自动检测读取,UTF-8 无 BOM 写入
var cfg = new CfgBuilder()
.AddJson("config.json", level: 0, writeable: true)
.Build();
// PowerShell 文件使用 UTF-8 带 BOM
var cfg = new CfgBuilder()
.AddJson("config.json", level: 0, writeable: true,
encoding: EncodingOptions.PowerShell)
.Build();
var options = new EncodingOptions
{
WriteStrategy = EncodingWriteStrategy.Preserve
};
var cfg = new CfgBuilder()
.AddJson("legacy.json", level: 0, writeable: true, encoding: options)
.Build();
var cfg = new CfgBuilder()
// 特定文件使用 GB2312 读取
.AddReadEncodingMapping(@"C:\legacy\old.ini", Encoding.GetEncoding("GB2312"))
// 所有 PS1 文件写入时使用 UTF-8 BOM
.AddWriteEncodingMappingWildcard("*.ps1", new UTF8Encoding(true))
// 正则匹配
.AddWriteEncodingMappingRegex(@"logs[/\\].*\.log$", Encoding.Unicode)
.AddJson("config.json", level: 0, writeable: true)
.Build();
var cfg = new CfgBuilder()
.ConfigureEncodingMapping(config =>
{
// 添加多条规则
config.AddReadMapping("*.xml", EncodingMappingType.Wildcard,
Encoding.UTF8, priority: 50);
config.AddWriteMapping("**/*.txt", EncodingMappingType.Wildcard,
new UTF8Encoding(true), priority: 10);
// 清除默认规则
config.ClearWriteMappings();
})
.WithEncodingConfidenceThreshold(0.8f) // 提高检测置信度阈值
.WithEncodingDetectionLogging(result => // 启用日志
{
Console.WriteLine($"检测到编码: {result}");
})
.AddJson("config.json", level: 0, writeable: true)
.Build();
| 符号 | 含义 | 示例 |
|---|---|---|
* |
匹配任意字符(不含路径分隔符) | *.json 匹配 config.json |
** |
匹配任意字符(含路径分隔符) | **/*.txt 匹配 a/b/c.txt |
? |
匹配单个字符 | config?.json 匹配 config1.json |
编码检测结果会被缓存以提高性能:
手动清除: EncodingDetector.ClearCache() 或 InvalidateCache(path)
// 禁用缓存
var options = new EncodingOptions { EnableCache = false };
// 手动清除缓存
FileCfgSourceBase.EncodingDetector.ClearCache();
EncodingDetector 构造时自动添加以下写入映射:
| 模式 | 编码 | 优先级 |
|---|---|---|
*.ps1 |
UTF-8 BOM | -100 |
*.psm1 |
UTF-8 BOM | -100 |
*.psd1 |
UTF-8 BOM | -100 |
这些默认映射优先级最低,可被用户配置覆盖。
| 变量名 | 说明 | 默认值 |
|---|---|---|
APQ_CFG_ENCODING_CONFIDENCE |
编码检测置信度阈值 | 0.6 |
| 方法 | 说明 |
|---|---|
AddReadEncodingMapping(path, encoding, priority) |
添加读取映射(完整路径) |
AddReadEncodingMappingWildcard(pattern, encoding, priority) |
添加读取映射(通配符) |
AddReadEncodingMappingRegex(pattern, encoding, priority) |
添加读取映射(正则) |
AddWriteEncodingMapping(path, encoding, priority) |
添加写入映射(完整路径) |
AddWriteEncodingMappingWildcard(pattern, encoding, priority) |
添加写入映射(通配符) |
AddWriteEncodingMappingRegex(pattern, encoding, priority) |
添加写入映射(正则) |
ConfigureEncodingMapping(Action<EncodingMappingConfig>) |
高级配置 |
WithEncodingConfidenceThreshold(float) |
设置置信度阈值 |
WithEncodingDetectionLogging(Action<EncodingDetectionResult>) |
启用检测日志 |
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
ReadStrategy |
EncodingReadStrategy |
AutoDetect |
读取策略 |
WriteStrategy |
EncodingWriteStrategy |
Utf8NoBom |
写入策略 |
ReadEncoding |
Encoding? |
null |
指定读取编码 |
WriteEncoding |
Encoding? |
null |
指定写入编码 |
FallbackEncoding |
Encoding |
UTF8 |
回退编码 |
ConfidenceThreshold |
float |
0.6 |
置信度阈值 |
EnableCache |
bool |
true |
启用缓存 |
EnableLogging |
bool |
false |
启用日志 |
| 名称 | 说明 |
|---|---|
EncodingOptions.Default |
默认配置 |
EncodingOptions.PowerShell |
PowerShell 脚本配置(UTF-8 BOM) |