Delphi - 从UTF-8转换回字符串

时间:2015-06-05 09:26:14

标签: macos delphi utf-8

我在将UTF-8编码的字符串转换回delphi可用的字符串时遇到问题。 该应用程序是用XE8编写的,并且正在Windows和OSX上部署。该应用程序分别在Windows和OSX上使用LimeLM API dll和dylib库。    在Windows上一切正常,我遇到的问题是转换从OSX上的dylib库返回的字符串。我很欣赏dylib中的所有字符串都必须是UTF-8编码的。   limeLM函数返回一个PWideChar值,我假设它是UTF编码的。但是我使用哪个函数来尝试将值转换为Delphi中可用的函数并不重要,我得到的只是垃圾。

这是功能:

class function TurboActivate.GetFeatureValue(featureName: String): String;
var
    value : PWideChar;
    FieldName : PWideChar;
    tmpStr : String;
begin

    {$IFDEF MSWINDOWS}
    FieldName := PwideChar(featureName);
    {$ENDIF}
    {$IFDEF MACOS}
    FieldName := PWideChar(UTF8Encode(featureName));
    {$ENDIF}


    value := GetFeatureValue(FieldName, nil);

    if (value = '') then
    begin
        raise ETurboActivateException.Create('Failed to get feature value.  the feature doesn''t exist.');
    end;
    {$IFDEF MSWINDOWS}
    Result := value;
    {$ENDIF}
    {$IFDEF MACOS}
    tmpStr :=  UTF8ToString(value);
    ShowMessage(tmpStr);
    tmpStr :=  UTF8ToWideString(value);
    ShowMessage(tmpStr);
    tmpStr :=  UTF8ToUnicodeString(value);
    ShowMessage(tmpStr);
    tmpStr :=  UTF8ToAnsi(value);
    ShowMessage(tmpStr);

    Result := TmpStr;
    {$ENDIF}

end; 

肯定有一个值可以解码, value ='散汤湡獤杀浔汧浥楡潣䌴䌴䅓䙇ⵊ䵙㑗㈭呖ⵆ倏呎尺'#4

但是tmpStr总是包含'????????????????????

感谢任何帮助。

1 个答案:

答案 0 :(得分:6)

  

value ='散汤湡獤杀浔汧浥楡潣潣䌴䅓䙇ⵊ䵙㑗㈭呖ⵆ倏呎'尺'#4

这表示您解释了8位文本,可能是UTF-8编码,就好像它是UTF-16编码的一样。作为一个宽泛的规则,当您看到带有中文字符的UTF-16字符串时,要么是正确解释的中文文本,要么是8位文本的错误解释。

当您将该文本正确解释为UTF-8时,它是:

cedlands@googlemail.com 4CSA-7GFJ-YMW4-2VTF-II5Q-BNTA♥♦

我用这段代码获得了:

  Writeln(TEncoding.UTF8.GetString(
    TEncoding.Unicode.GetBytes('散汤湡獤杀潯汧浥楡⹬潣m䌴䅓㜭䙇ⵊ䵙㑗㈭呖ⵆ䥉儵䈭呎́'#4)));

但请注意,如果查看TEncoding.Unicode.GetBytes('散汤湡獤杀潯汧浥楡⹬潣m䌴䅓㜭䙇ⵊ䵙㑗㈭呖ⵆ䥉儵䈭呎́'#4)返回的字节数组,则会看到它包含空值。实际上,字符串在电子邮件地址之后以空值终止。

问题从这里开始:

value : PWideChar;
....
value := GetFeatureValue(FieldName, nil);

实际上GetFeatureValue会返回PAnsiChar。并且有效载荷是UTF-8编码的,假设我正确地解释了你。

所以你需要做出以下改变:

  1. GetFeatureValue的返回类型更改为PAnsiChar
  2. value的类型更改为PAnsiChar
  3. 使用valueUnicodeFromLocaleChars将<{1}}转换为字符串。
  4. 这可能是这样的:

    TEncoding.GetString

    现在,针对将var Bytes: TBytes; .... SetLength(Bytes, StrLen(value)); Move(value^, Pointer(Bytes)^, Length(Bytes)); str := TEncoding.UTF8.GetString(Bytes); 设置为str的问题中的数据。如上所述,数据包含一个空终止符,当它被错误地解释为UTF-16时,它无法终止该字符串。也就是说,文本cedlands@googlemail.com来自缓冲区溢出。