EDF+ 文件头区长度与字节布局(实现视角)

本文从 EDF+ 写入库EDFwriter.java 类注释与 prepareForResume / write_edf_header 实现)归纳头区布局,便于与「按 record 对齐修复 / 续写」等逻辑对照。规范原文见 EDF/EDF+ 说明

1. 头区总长度是否固定?

不固定。 头区总字节数随 数据信号数 edfsignals注释信号数 nr_annot_chns 变化。实现中与 prepareForResume 一致:

headerSize = (edfsignals + nr_annot_chns + 1) × 256

含义:1 块主头(256 字节) + 每个数据信号各 1 块 256 字节信号头 + 每条注释信号各 1 块 256 字节信号头

常见配置:nr_annot_chns = 1EDF Annotations),数据通道 edfsignals = 5 时:

headerSize = (5 + 1 + 1) × 256 = 7 × 256 = 1792 字节

若通道数或注释轨数不同,只需代入同一公式即可。

2. 主头:第一个 256 字节(文件偏移 0~255)

主头为 ASCII 左对齐、空格填充,无 NUL。类注释中的偏移与长度如下(十进制偏移相对文件开头):

起始偏移 长度 含义
0 8 版本(如 0 表示 EDF)
8 80 患者本地标识
88 80 录制本地标识
168 8 录制开始日期 dd.mm.yy
176 8 录制开始时间 hh.mm.ss
184 8 头记录总字节数(应与 headerSize 一致)
192 44 保留
236 8 数据记录条数(写入过程中可为 -1 表示未知;close() 时会回写为实际条数)
244 8 每条 data record 的持续时间(秒)
252 4 信号数量(数据信号 + 注释信号,ASCII 数字)

续写 / 修复时从盘上读取起始时刻,应对齐 168、176 各 8 字节,解析为年、月、日、时、分、秒,再交给 prepareForResume,以便重写的头与文件已有内容一致。

正常收尾时,实现会在偏移 236 处写入当前 完整 data record 条数(8 字符 ASCII),然后执行注释区写入等步骤。

3. 信号头:第 2 块起的多个 256 字节

紧跟主头之后,每个信号(含数据通道与 EDF Annotations 通道)各占 256 字节,块内再按规范细分,例如(相对「本块」起点 0 的常用划分,与类注释一致):

块内偏移 长度 含义
0 16 信号标签
16 80 传感器 / 换能器
96 8 物理量纲
104 8 物理最小值
112 8 物理最大值
120 8 数字最小值
128 8 数字最大值
136 80 预滤波等
216 8 本信号在每条 data record 中的样本数(与 recordsize 推导直接相关)
224 32 保留

数据通道与注释通道各重复上述 256 字节 结构;注释通道标签在实现中常为 EDF Annotations (长度不足处用空格填满字段宽)。

4. 与「数据区」的衔接

头区结束后,从字节偏移 headerSize 开始,是 连续多条等长 data record,每条长度为 recordsize(由各通道「每 record 样本数」、EDF 每样本 2 字节、以及注释轨在每 record 内占用字节等共同决定,在 write_edf_header 内汇总)。

修复逻辑里常用:

payloadSize = fileLength - headerSize
completeRecords = floor(payloadSize / recordsize)

即:只有头长与 record 长度都一致时,才能唯一划分「头 + N 条完整 record」;尾部不足一整条的部分会被截断策略处理(见仓库内 edf-resume 相关笔记)。

5. 小结

问题 结论
所有 EDF 文件头长一样吗? ,由 (edfsignals + nr_annot_chns + 1) × 256 决定。
5 数据 + 1 注释时多长? 1792 字节
每个字节怎么查? 先按 256 字节分块:第 0 块用主头表;第 1…块用信号头子偏移表。

文档由仓库内技术说明整理,用于设计与联调对照。