在CATIA CAA二次开发中,字符串处理确实是一个容易让人掉进“乱码陷阱”的重灾区。CATUnicodeString(以下简称 CUS)虽然是达索提供的标准类,但它确实不是万能的,尤其是在涉及外部文件 IO、数据库交互或调用第三方 C++ 库时。
要彻底解决编码问题,需要理解 CATIA 内部与外部世界的“翻译”机制。
1. 理解 CATIA 的“三界”编码
在 CAA 开发中,字符串通常在三个层面流动:
-
CATIA 内部界 (UTF-16):
CATUnicodeString内部存储使用的是 UTF-16。只要是在 CATIA 界面(对话框、特征树)上显示,用它就对了。 -
操作系统/外部库界 (MBCS/UTF-8):
传统的 C 库(如
fopen)或第三方库通常期望char*。这里涉及系统 CodePage(如 GBK)或标准的 UTF-8。 -
代码/硬编码界:
你在 Visual Studio 里写下
L"内容"或"内容",其编码取决于源代码文件的保存格式(建议统一使用 UTF-8 with Signature)。
2. CATUnicodeString 的核心转换方法
不要直接强转 char*。你应该根据目标场景,显式调用 CUS 的转换函数:
A. 转换为系统本地编码 (Local CodePage)
如果你要调用 printf 或将路径传递给不支持 Unicode 的旧式 C 函数,使用 ConvertToChar。
CATUnicodeString myString = "中文内容";
char* localBuffer = NULL;
// 转换为当前操作系统的语言编码(如 Windows 简体中文下的 GBK)
myString.ConvertToChar(&localBuffer);
// 使用完记得释放内存
delete[] localBuffer;
localBuffer = NULL;
B. 转换为 UTF-8 (跨平台/Web/现代库)
如果你在处理 JSON 或调用现代第三方库,通常需要 UTF-8。
CATUnicodeString myString = ...;
int length = 0;
// 获取转换为 UTF-8 后所需的字节长度
myString.BuildFromUTF8(NULL, 0); // 这是一个技巧,或者直接通过转换函数
// 推荐使用专用方法:
CATIDOMString domString; // 有时利用 XML 模块的类转换更稳健
注:CAA 早期版本对 UTF-8 支持较弱,有时需要通过 CATUnicodeString::BuildFromWChar 配合 Windows API WideCharToMultiByte 来完成转换。
3. 常见痛点与解决方案
痛点一:从 char* 读取乱码
如果你的 char* 来自一个 UTF-8 编码的文件,直接 CATUnicodeString(myChar) 会导致乱码,因为它默认按本地 CodePage 解析。
-
正确做法:
使用
BuildFromUTF8。
constchar* utf8Data = "...";
CATUnicodeString cus;
cus.BuildFromUTF8(utf8Data, strlen(utf8Data));
痛点二:路径处理
这是最容易崩的地方。CATIA 官方推荐在处理文件系统时,尽量使用 CATLib 库中的函数(如 CATGetFilePath),这些函数通常接受 CATUnicodeString 并能处理长路径和特殊字符。
- 如果必须传
char*给底层,确保路径中没有非 ASCII 字符,否则必须转为 System Locale。
痛点三:硬编码字符串
在代码里写 CATUnicodeString str = "确定"; 是危险的。
-
方案:
使用 CATNls 文件。将字符串放在
.CATNls文件中,通过CATMsgCatalog读取。这是 CATIA 官方标准的国际化做法,能自动处理所有编码映射。
4. 最佳实践建议
| 场景 | 推荐做法 |
|---|---|
| 界面显示 (UI) | 始终使用 CATUnicodeString + CATNls 资源文件。 |
| 文件 IO | 使用 CATFSTream 或 CATFEABFile 等封装类,它们对 CUS 支持更好。 |
| 调试打印 | 转换回 char* 使用 cout 或利用 CATUnicodeString::CastToCharPtr() (慎用)。 |
| 跨模块传递 | 统一使用 CATUnicodeString 作为参数类型。 |
避坑指南:
不要信任
(char*)cus这种强转。 CUS 不是简单的std::string封装。它的内存布局在不同版本间可能变化,务必通过显式的转换接口获取数据副本。
评论