在Delphi 2007中,您可以将UTF-8字符串存储在WideString中,然后将其传递给Win32函数,例如
var
UnicodeStr: WideString;
UTF8Str: WideString;
begin
UnicodeStr:='some unicode text';
UTF8Str:=UTF8Encode(UnicodeStr);
Windows.SomeFunction(PWideChar(UTF8Str), ...)
end;
Delphi 2007不会干扰UTF8Str的内容,即它保留为存储在WideString中的UTF-8编码字符串。
但是在Delphi 2010中,我很难找到一种方法来做同样的事情,即将一个UTF-8编码的字符串存储在WideString中,而不会自动从UTF-8转换。我无法传递指向UTF-8字符串(或RawByteString)的指针,例如以下显然不起作用:
var
UnicodeStr: WideString;
UTF8Str: UTF8String;
begin
UnicodeStr:='some unicode text';
UTF8Str:=UTF8Encode(UnicodeStr);
Windows.SomeFunction(PWideChar(UTF8Str), ...)
end;
答案 0 :(得分:13)
您的原始Delphi 2007代码使用ANSI代码页将UTF-8字符串转换为宽字符串。要在Delphi 2010中执行相同的操作,您应该使用SetCodePage和Convert参数false。
var
UnicodeStr: UnicodeString;
UTF8Str: RawByteString;
begin
UTF8Str := UTF8Encode('some unicode text');
SetCodePage(UTF8Str, 0, False);
UnicodeStr := UTF8Str;
Windows.SomeFunction(PWideChar(UnicodeStr), ...)
答案 1 :(得分:3)
因为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和string(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;
我检查过,它的工作原理是一样的。因为我直接在内存中移动字节,所以后台没有进行代码页转换。我相信它可以通过更大的元素来完成,但关键是我认为这是你想要实现的目标。
答案 2 :(得分:0)
哪个Windows API调用要求您传递UTF-8字符串?它是ANSI字符串或Widestring(A或W函数)。 Widestrings每个字符有两个字节,UTF-8字符串有一个(如果超出前128个ASCII字符,则为更多)。
Widestring中的UTF-8没有意义。当真的有一个想要指向UTF-8字符串的Windows函数时,你可能需要将其转换为PAnsiChar。