CAPL 编程系列教程 - 第二十五期:常用内置函数之读取文本文件

CAPL 编程系列教程的第二十五期内容 ,主要讲解如何在 CAPL 中读取文本文件的内容。

CAPL 编程系列教程 - 第二十五期:常用内置函数之读取文本文件

一、 课程回顾与本期目标

  • 回顾前面学习了 CAPL 的事件驱动模型、系统测量事件、报文接收事件 (on message)、信号事件 (on signalon signal_update)、系统变量on sysvar 和 on sysvar_update
  • 本期目标: 学习使用 CAPL 内置的文件操作函数来读取文本文件 (.txt) 中的内容。
  • 应用场景: 在自动化测试脚本中,经常需要从外部文件读取配置信息、测试数据、用例参数等。

二、 读取文本文件的基本步骤 (三部曲)

  1. 打开文件: 使用特定函数打开要读取的文件,获取一个文件句柄File Handle (文件在内存中的地址)。
  2. 读取内容: 使用特定函数从打开的文件中逐行读取文本内容到 CAPL 的字符数组变量中。
  3. 关闭文件: 读取完成后,使用特定函数关闭文件,释放资源。

三、 涉及的 CAPL 函数

  1. openFileRead(char filePath[], int mode)

    • 作用: 打开指定路径的文件,用于读取
    • 参数:
      • filePath: 包含文件路径和名称的字符串
        • 可以是相对路径,相对于 CANoe 工程文件 (.cfg) 所在的目录。推荐将数据文件放在工程目录下的子文件夹中(如 Files),路径写为 "Files\\data.txt" (注意可能需要双反斜杠 \\ 或使用正斜杠 /)。
        • 也可以是绝对路径 (如 "C:\\MyData\\data.txt")。
      • mode: 打开模式。
        • 0: 文本模式 (Text Mode) - 按字符读取,通常用于读 .txt 文件。
        • 1: 二进制模式 (Binary Mode) - 按字节读取,用于读二进制文件。
    • 返回值 (dword):
      • 返回一个文件句柄 (File Handle),这是一个非零的整数值,代表成功打开的文件。后续的读写操作都需要使用这个句柄。
      • 如果文件打开失败(如文件不存在、路径错误、权限问题),返回 0
  2. fileGetString(char buffer[], long bufferSize, dword fileHandle)

    • 作用: 从指定的文件句柄 fileHandle 指向的文件中读取一行文本内容,并将其存入字符数组 buffer 中。会包含行尾的换行符 (\n) (如果存在的话)。
    • 参数:
      • buffer: 目标字符数组 (字符串缓冲区),用于存储读取到的行内容。
      • bufferSize: 缓冲区的大小 (通常使用 elcount(buffer) 获取),限制一次最多读取的字符数(包括 \0),防止溢出。
      • fileHandle: 由 openFileRead 返回的文件句柄。
    • 返回值 (long):
      • 1: 表示成功读取了一行。
      • 0: 表示已到达文件末尾 (EOF) 或发生读取错误。
  3. fileGetStringSZ(char buffer[], long bufferSize, dword fileHandle) (SZ 可能代表 Strip Zero 或 Size?)

    • 作用: 与 fileGetString 类似,也是读取一行文本,但会自动去除行尾的换行符 (\n)
    • 参数: 同 fileGetString
    • 返回值 (long): 同 fileGetString (1 表示成功,0 表示 EOF 或错误)。
    • 推荐: 如果不希望读入换行符,推荐使用此函数。
  4. fileClose(dword fileHandle)

    • 作用: 关闭由 fileHandle 指定的已打开文件,释放相关资源。
    • 参数: fileHandle: 要关闭的文件的句柄。
    • 返回值: 通常不关心其返回值,但可以检查是否成功关闭。
    • 重要: 打开文件后,务必在读取完成或不再需要时调用此函数关闭文件,避免资源泄漏。

四、 读取整个文件的实现逻辑 (使用循环)

  • 思路: 由于 fileGetStringfileGetStringSZ 一次只读一行,要读取整个文件,需要使用循环结构(如 while)。
  • 循环条件: 利用读取函数的返回值作为循环条件。当函数返回 1 (表示成功读取) 时继续循环,当返回 0 (表示到达文件末尾或出错) 时停止循环。
  • 实现:
    Code snippet
    variables {
      char lineBuffer[200]; // 定义足够大的行缓冲区
      dword fh;             // 文件句柄
    }
    
    on key 'a' {
      // 1. 打开文件
      fh = openFileRead("Files\\data.txt", 0); 
    
      // 检查文件是否成功打开
      if (fh == 0) {
        write("错误:无法打开文件!");
        return; // 或者进行其他错误处理
      }
    
      // 2. 循环读取文件内容
      // while (fileGetString(lineBuffer, elcount(lineBuffer), fh)) // 读取包含换行符
      while (fileGetStringSZ(lineBuffer, elcount(lineBuffer), fh)) // 读取不包含换行符
      { 
        // 循环条件为真 (即读取成功,返回 1) 时执行循环体
        write("读取到的一行内容为: %s", lineBuffer); 
        // 可以在这里处理 lineBuffer 中的内容...
      }
      // 循环结束后,说明已到文件末尾或出错 (读取函数返回 0)
    
      // 3. 关闭文件
      fileClose(fh);
    
      write("***** 文件内容已经读取完毕了 *****");
    }
    

五、 注意事项与补充

  • 文件编码: 教程提到,如果文本文件中包含中文字符,直接使用上述函数读取可能会失败或乱码。这通常与文件的编码格式(如 ANSI/GBK, UTF-8 等)有关。
    • 解决方案提示: 教程未详细说明,但暗示可能有其他方式或需要特定设置来处理中文编码。(补充:在 CAPL 中处理非 ASCII 编码文件可能需要使用支持编码的函数(如 fileOpen 的某些模式参数或特定库函数),或者确保文件保存为 CANoe/CAPL 默认能识别的编码(如带有 BOM 的 UTF-8 或系统默认 ANSI 编码),具体需查阅 CAPL 文档或进行实验。)
  • 错误处理: openFileRead 返回 0 表示打开失败,实际应用中应进行检查和处理。fileGetString/SZ 返回 0 也可能是读取错误,而非仅 EOF,严格来说也应考虑区分。
  • 缓冲区大小: 确保定义的字符数组缓冲区足够大,能容纳文件中可能出现的最长行。

六、 总结与后续

  • 本期学习了在 CAPL 中读取文本文件的标准三步流程:打开 (openFileRead)、逐行读取 (fileGetStringfileGetStringSZ)、关闭 (fileClose)。
  • 掌握了如何在循环中结合读取函数的返回值来读取整个文件的内容。
  • 理解了 fileGetStringfileGetStringSZ 在处理换行符上的区别。
  • 文件读取是 CAPL 脚本与外部数据交互的重要手段,为后续读取配置文件、测试用例等打下基础。