直接用 StreamReader 读 VCF 会漏关键字段,因 VCF 是结构化文本,需先解析##INFO/##FORMAT元数据构建类型映射,INFO/FORMAT须按定义解析而非简单切分,且应避免全量加载与硬编码解析逻辑。

为什么直接用 StreamReader 读 VCF 会漏掉关键字段
因为 VCF 是带结构的文本格式,不是纯行式日志。头部有 ##INFO、##FORMAT 等元数据定义字段含义,主体里 INFO 和 FORMAT 列的值依赖这些定义才能正确解析。跳过头部或硬拆 \t 会导致 AF=0.33 这种键值对被当字符串切开,丢失语义。
- 必须先扫描所有
##行,构建INFO和FORMAT字段的类型映射(比如ID=AF对应Float) -
CHROM、POS、REF、ALT这些固定列可直接按索引取,但INFO列需用分号分割后查表解析 - 如果只关心少数字段(如
AF、DP),别全量解析INFO字符串,避免重复 split 和字典查找
VcfRecord 类该暴露哪些属性才不踩坑
别把 INFO 暴露成 string 或 Dictionary<string, string> —— 前者无法做类型安全访问,后者强制你每次都要手动转换 AF 的 string 为 double,且忽略缺失值(.)和数组(AC=1,2)。
- 用泛型方法提供类型化访问:
record.GetInfoValue<double>("AF"),内部处理.→null、逗号分隔 →double[] -
FORMAT字段必须绑定到对应样本(SAMPLE列),不能只存一个Dictionary;每个样本应有独立的VcfSampleData实例 - 别缓存原始
INFO字符串字段——它易变且无结构,后续加字段或改顺序时逻辑会悄无声息地坏掉
用 System.Text.Json 序列化 VCF 记录时的兼容性陷阱
VCF 的 ALT 可能是 <DEL>、<INS:ME:ALU> 这类结构化符号,JSON 默认反序列化会报错或丢数据,因为 < 和 > 在 JSON 字符串里合法但容易被误判。
- 自定义
JsonConverter<string>,对ALT、INFO键名等字段做转义绕过(比如把<替成__LT__),别依赖默认行为 - 如果要导出为 JSON 供前端展示,优先用
Dictionary<string, JsonElement>而非强类型类——VCF 的INFO字段在不同数据集间差异极大,硬建模必裂开 -
POS是 1-based 坐标,序列化前别转成 0-based;下游工具(如 IGV)认的是标准 VCF 定义,改了就对不上
大 VCF 文件(>1GB)内存暴涨的真正原因
不是因为文件大,而是因为默认用 File.ReadAllLines() 或一次性加载所有 VcfRecord 实例。每个记录即使只存几个字段,.NET 对象头 + 字符串对象开销会让内存占用翻 3–5 倍。
- 用
FileStream+StreamReader流式读,每行解析完立刻生成轻量VcfRecordView(只存字段索引和原始字节偏移,不存字符串副本) - 需要随机访问时,先用
IndexBuilder扫描一遍生成.tbi类似索引(即行号 → 文件偏移映射),而不是把整文件塞进List<VcfRecord> - 警惕 LINQ 的
Where+ToList组合——它会触发全量加载,哪怕你只想要第 100 行
最麻烦的其实是 INFO 字段的嵌套结构:一个 CSQ 可能含几十个子字段,且分隔符是 | 而不是逗号。解析时没设上限,遇到畸形行就卡死或爆栈。这事没法靠文档预防,得在代码里写死最大子字段数并加 try/catch。










