了解Rad Studio中的UTF8Encode和UTF8ToString

时间:2016-07-04 08:46:17

标签: delphi c++builder

由于遗留原因,我需要使用在Rad Studio中使用AnsiString而不是UnicodeString的旧源。

所以,我的计划是大部分时间都使用String,当我需要使用这个库时,转换为AnsiString,并且尽快从AnsiString转换为String。

String temp = L"汉语/漢語";
AnsiString raw=UTF8Encode(temp);
String dest = UTF8ToString(raw);

当我检查时,我得到了???而不是汉语/汉语。我做错了什么?

2 个答案:

答案 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将接受这一点。

如果你想真正冒险,你应该更新库以使用AnsiStringTtypedef 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用于二进制数据,但我无法重写库。