由于遗留原因,我需要使用在Rad Studio中使用AnsiString而不是UnicodeString的旧源。
所以,我的计划是大部分时间都使用String,当我需要使用这个库时,转换为AnsiString,并且尽快从AnsiString转换为String。
String temp = L"汉语/漢語";
AnsiString raw=UTF8Encode(temp);
String dest = UTF8ToString(raw);
当我检查时,我得到了???而不是汉语/汉语。我做错了什么?
答案 0 :(得分:2)
在Delphi / C ++ Builder 2009及更高版本中,您需要远离使用AnsiString
作为二进制缓冲区。它是一个代码分片字符串,当字符串被传递时,它可能导致从一个代码页到另一个代码页的细微/意外数据转换。在您的情况下,???
是实际转换为Ansi代码页的数据的直接结果,该Ansi代码页不支持您尝试使用的Unicode字符。
你真的应该使用TBytes
来获取二进制数据。对于UTF-8编码的字符串,请改用UTF8String
:
String temp = L"汉语/漢語";
UTF8String raw = UTF8String(temp);
...
String dest = String(raw);
话虽如此,因为您必须与期望UTF-8编码AnsiString
作为二进制缓冲区 1 的第三方库互操作,那么您至少可以使用{ {1}}变量并在将{(1}}传递给库时将其输入(不分配):
UTF8String
或者:
AnsiString
这是有效的,因为library_function(*(reinterpret_cast<AnsiString*>(&raw));
,library_function(reinterpret_cast<AnsiString&>(raw));
和AnsiString
都基于相同的UTF8String
基类型:
RawByteString
因此所有人共享一个共同的内存布局和实现,Delphi将接受这一点。
如果你想真正冒险,你应该更新库以使用AnsiStringT
或typedef AnsiStringT<0> AnsiString;
typedef AnsiStringT<65001> UTF8String;
typedef AnsiStringT<65535> RawByteString;
(如果不是RawByteString
)而不是UTF8String
,那么你就不要所有 2 :
TBytes
1 :你真的需要获得该库的新版本,或者使用不同的库。
2 :这是AnsiString
最初打算用于的情况。它从不打算用于独立变量,而是用于可以接受任何类型的8位字符串作为输入而不执行数据转换的函数参数。
答案 1 :(得分:0)
目前,我找到了一个解决方案:
AnsiString UTF8ToBin(UTF8String value)
{
AnsiString dest;
dest.SetLength(value.Length());
memcpy(dest.c_str(), value.c_str(), value.Length());
return dest;
}
它允许我使用AnsiString类型的库来存储二进制数据,在本例中为UTF8。
我很清楚我需要将TBytes用于二进制数据,但我无法重写库。