您需要避免在Delphi/C++Builder 2009及以后版本中使用
AnsiString
作为二进制缓冲区。这是一种编码过的字符串,会导致隐晦/意外的数据转换从一个代码页到另一个,因为字符串被传递。在您的情况下,
???
是实际上被转换为不支持您尝试使用的Unicode字符集的Ansi代码页的直接结果。
您真正应该使用
TBytes
来处理二进制数据。对于UTF-8编码的字符串,请改用
UTF8String
。
String temp = L"汉语/漢語";
UTF8String raw = UTF8String(temp);
...
String dest = String(raw);
话虽如此,由于您需要与期望作为二进制缓冲区的 UTF-8 编码 AnsiString
进行交互的第三方库进行互操作1,因此您至少可以使用一个 UTF8String
变量,并在传递给库时将其类型转换(而不是分配)为 AnsiString
:
library_function(*(reinterpret_cast<AnsiString*>(&raw));
或者:
library_function(reinterpret_cast<AnsiString&>(raw));
这能够工作是因为
AnsiString
、
UTF8String
和
RawByteString
都基于同一
AnsiStringT
基础类型。
typedef AnsiStringT<0> AnsiString;
typedef AnsiStringT<65001> UTF8String;
typedef AnsiStringT<65535> RawByteString;
因此,它们都共享一个通用的内存布局和实现方式,Delphi也可以正常接受。
如果你想更加冒险一些,你应该更新库以使用RawByteString
或UTF8String
(如果不使用TBytes
),而不是AnsiString
,这样就完全不需要进行类型转换2:
library_function(raw);
1: 你真的需要获取该库的新版本或使用不同的库。
2: 这种情况是最初RawByteString
所设计用于的。它并不是为了独立变量而设计的,而是为了函数参数可以接受任何类型的8位字符串作为输入而不进行数据转换。
AnsiString
。你需要停止这样做。你需要使用 Unicode 编码来保存你的数据。ANSI 无法完成任务。可以使用 UTF-16 或 UTF-8,但不能使用 ANSI。如果没有了解遗留动机,很难指导你找到解决方案。 - David HeffernanAnsiString
存储二进制数据是非常古老的方法,是在动态数组 (of Byte
) 出现之前的一种糟糕的做法。 - Free Consulting