嗯,你为什么要这么做?为什么要将 WideString 编码为 UTF-8 只是为了将其再次存储回 WideString。您显然使用的是 Unicode 版本的 Windows API。所以没有必要使用 UTF-8 编码的字符串。或者我错过了什么。
因为 Windows API 函数要么是 Unicode(两个字节),要么是 ANSI(一个字节)。UTF-8 在这里是错误的选择,因为它主要是每个字符包含一个字节,但对于 ASCII 基以上的字符,它使用两个或更多字节。
否则,您在 unicode Delphi 中的旧代码的等价物将是:
var
UnicodeStr: string;
UTF8Str: string;
begin
UnicodeStr:='some unicode text';
UTF8Str:=UTF8Encode(UnicodeStr);
Windows.SomeFunction(PWideChar(UTF8Str), ...)
end;
WideString 和字符串 (UnicodeString) 类似,但新的 UnicodeString 更快,因为它是引用计数的,而 WideString 不是。
您的代码不正确,因为 UTF-8 字符串每个字符的字节数是可变的。“A”存储为一个字节。只是一个 ASCII 字节码。另一方面,“ü”将存储为两个字节。并且因为您使用的是 PWideChar,所以该函数始终需要每个字符两个字节。
还有另一个区别。在较旧的 Delphi 版本 (ANSI) 中,Utf8String 只是一个 AnsiString。在 Unicode 版本的 Delphi 中,Utf8String 是一个带有 UTF-8 代码页的字符串。所以它的行为不同。
旧代码仍然可以正常工作:
var
UnicodeStr: WideString;
UTF8Str: WideString;
begin
UnicodeStr:='some unicode text';
UTF8Str:=UTF8Encode(UnicodeStr);
Windows.SomeFunction(PWideChar(UTF8Str), ...)
end;
它的行为与 Delphi 2007 中的行为相同。所以也许你在其他地方有问题。
米克你是对的。编译器在幕后做了一些额外的工作。因此,为了避免这种情况,您可以执行以下操作:
var
UTF8Str: AnsiString;
UnicodeStr: WideString;
TempString: RawByteString;
ResultString: WideString;
begin
UnicodeStr := 'some unicode text';
TempString := UTF8Encode(UnicodeStr);
SetLength(UTF8Str, Length(TempString));
Move(TempString[1], UTF8Str[1], Length(UTF8Str));
ResultString := UTF8Str;
end;
我检查了,它的工作原理是一样的。因为我直接在内存中移动字节,所以没有在后台进行代码页转换。我相信它可以更优雅地完成,但重点是我认为这是你想要实现的方式。