CAPL Script

CAPL 文件读写验证:先确认数据完整,再分析 CSV

问题:调用成功,数据仍可能错误

文件打开成功、连续几次读取成功、统计图也看起来合理,并不能证明读的是目标文件、每次读到的都是完整记录,或导出包含了全部样本。本指南用可以手工核对的小型临时文件,将这些问题分别验证。

适用范围是本地 CANoe/CAPL 工作流,每个物理文本行只包含一个数值时间戳。它不是通用 CSV 解析器、二进制 Trace 转换器,也不是分布式测试方案。下文的 API 行为以本站持有授权的 Vector 参考资料为依据;验证矩阵是本站编写的检查方法,并非已经执行的 CANoe 编译或实测结果。

打开文件前,先写清输入输出约定

明确预期目录、文件名、编码、时间单位、最大记录长度、记录数量和空行处理方式。测试文件与测量原件分开保存。第一轮只使用 ASCII 数字和小数点,避免编码问题掩盖记录边界错误。

要做的事 可采用的选择 防止的错误
重建一个完整的临时导出文件 文本覆盖,模式 0 混入上一段记录
继续写入已知文本文件 先检查末尾分隔符和时间连续性,再使用追加模式 2 两条记录粘连或时间戳重新归零
保留判断行边界所需的信息 fileGetString,加有长度上限的记录组装 把一次读取的片段误当成整行
读取已确认足够短、结果不需要 LF 的文本行 fileGetStringSZ,并验证长度上限 减少去换行步骤;仍不能省略超长记录检查
读取二进制采集文件 使用理解该文件格式的二进制处理流程 把任意字节当成数值文本

根据可用参考资料,openFileRead(英文参考)先搜索数据库所在目录,再使用当前配置目录。openFileWrite(英文参考)使用相对文件名,输出基目录由写路径决定,未设置时使用配置目录。两者的定位规则不同。因此,回读同名文件,不等于已经读到刚刚写出的那个文件。

用独特文件名和可辨认的标记内容确认实际来源。打开前准备并核对输出目录,不要假定 API 自动创建目录。setWritePath 的可用参考明确排除了分布式环境,迁移该方案前必须核实安装版本和环境支持。

将读取、组装和数值解析分开

可靠的处理顺序是:读取成功 → 得到长度受控的完整记录 → 验证数值。第一步成功,不能跳过第二步。

例如缓冲容量为 8 时,一次调用最多读取 7 个字符。对于 123456789 这一行,先读到的 1234567 本身也是合法数字,但不是正确记录。确定完整记录以前,不要更新样本计数或统计值。超过约定记录长度时,应报出记录位置并拒绝导入;如果选择跳过,就必须丢弃到该记录的真正边界,不能把剩余后缀当作下一条时间戳。

fileGetString 遇到行边界时会在结果中保留 LF;fileGetStringSZ 不把 LF 放进结果。两者都受 buffsize - 1 限制。CANoe 12 原始帮助的 fileGetStringSZ 说明列出了 LF 和 CRLF(DOS)两种行尾。下面分别测试两种夹具及返回字节;支持的输入形式本身不能证明所有安装版本的字节归一化行为相同。

每次尝试读取前,使应用层的当前记录失效;只有读取成功才继续解析。不要依赖失败调用清空缓冲区。否则,在最后一条记录之后读取失败时,旧内容可能再次被统计,造成重复时间戳。

可用文档将读取返回值定义为 1 或 0,并把 0 描述为错误,没有给出可以单独证明“正常到达 EOF”的返回约定。因此,尚未解释的停止应记录为“读取终止”。对于测试文件,可核对已知数量与内容;对于生产数据的完整性,需要使用安装版本明确支持的诊断方法,或其他独立的完整性检查。读了一部分就停止,不能自动视为一个有效的小数据集。

用小文件建立验证矩阵

表中的 \n 表示 LF,\r\n 表示 CRLF;制作测试文件时应写入实际分隔符,而非反斜杠字面字符。以下为设计输入与预期的应用行为,不是已执行结果。

测试文件或操作 要观察什么 验收条件
0\n10\n20\n 读取片段、有效记录和最后一次读取状态 按顺序得到三个值,不重复最后一个值
相同数值改用 CRLF 返回字符及解析后的值 按声明的行尾规则得到相同数值记录
空文件 是否错误处理了旧缓冲内容 零个值,并明确报告输入为空
0\n\n10\n 中间的空物理行 明确跳过或拒绝,不静默转换成 0
0\n10,末尾没有分隔符 最后一条未终止行的处理 明确且经过验证地接受完整末项或拒绝,不能从后续失败读取中造出记录
长度恰好到达、以及超过所选容量边界的记录 片段长度与组装状态 仅在长度约定内接受完整记录,不拆成多个时间戳
不存在的文件名 打开返回值 不使用句柄 0 继续读取
候选搜索目录中存在不同内容的同名文件 实际读到哪个标记 继续其他测试前消除来源歧义
临时输出文件已有 OLD\n 模式 0 和模式 2 的差异 覆盖与追加符合预先约定
旧文件末尾为 20,再追加 30\n 是否拼成 2030 应用阻止或拒绝这种不安全的追加

保留测试原件、CANoe 版本、当前配置、API 变体、缓冲容量、打开/读取/写入/关闭状态,以及接受的记录数。只保留最后的平均值,会丢失解释失败原因所需的证据。

写入返回值不是字节数

filePutString(英文参考)接收要写入的字符数量,成功返回 1,错误返回 0。即使请求写入 20 个字符,成功结果仍然是 1。不能拿返回值与 20 比较,更不能因为不相等就重试整条记录。

长度应来自准备写入的有效文本,而不是存储数组的容量。记录分隔符必须明确包含在文本中。任何一次写入失败后,都不能继续宣布导出成功;文档中的状态值没有说明失败时是否已经写入部分内容,因此不能假定直接重试安全。完成后检查 fileClose(英文参考)并查看实际文件;关闭成功也不能抹掉此前的写入失败。

每个句柄由一个操作负责管理。每次成功打开后,正常完成、解析拒绝和用户中止都要走清理路径。不要用新打开的结果覆盖尚未关闭的句柄,也不要在确认关闭后复用旧值。清理失败应与原始错误分别报告,并阻止该操作继续使用句柄。

将验证过的时间戳送入间隔分析工具

先完成文件往返验证,再使用一个仅含 0、10、20、31 的单列合成样本,单位选择毫秒。相邻差值应为 10、10、11 ms。手算核对这些数对后,再在报文时间间隔分析工具中比较结果。

工具接受它明确支持的时间戳列表或单列 CSV,不负责解析包含通道、ID 和数据域的通用 CANoe 日志。先提取时间戳列、保留原始顺序并确认单位。处理真实流量时,按照测量同一 CAN 报文周期的方法选定连续的单一报文流。文件完整,只能证明文件处理这一环节,不能证明选取的流量回答了原本的测量问题。

参见资料来源与验证边界。用于必须证明完整性的测试前,应对照安装版本自带帮助,核实函数签名、支持范围,以及本文来源尚未明确的 EOF 和编码细节。