Delphi - 将字符串从 UTF-8 转换回
Delphi - converting string back from UTF-8
我在将 UTF-8 编码字符串转换回 delphi 可用的内容时遇到问题。
该应用程序是用 XE8 编写的,正在 windows 和 OSX 上部署。该应用程序分别在 windows 和 OSX 上使用 LimeLM API dll 和 dylib 库。
在 windows 上一切正常,我遇到的问题是转换从 OSX 上的 dylib 库返回的字符串。我很欣赏所有进出 dylib 的字符串都需要采用 UTF-8 编码。
limeLM 函数 returns 一个 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 = '散汤滩杀豪汧浥楡潣m伴侣仓㜭万ⵊ佑㑗㈭喔ⵆ义势䈭嘶'#4
但 tmpStr 始终包含 '??????????c??????/'
如有任何帮助,我们将不胜感激。
value = '散汤湡獤杀潯汧浥楡潣m䌴䅓㜭䙇ⵊ䵙㑗㈭呖ⵆ䥉儵䈭呎́'#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)
编辑的字节数组 return,您会发现它包含一个空值。所以实际上该字符串在电子邮件地址之后以 null 结尾。
问题从这里开始:
value : PWideChar;
....
value := GetFeatureValue(FieldName, nil);
事实上GetFeatureValue
returns PAnsiChar
。有效载荷是 UTF-8 编码的,假设我对你的解释是正确的。
因此您需要进行以下更改:
- 将
GetFeatureValue
的 return 类型更改为 PAnsiChar
。
- 将
value
的类型更改为 PAnsiChar
。
- 使用
UnicodeFromLocaleChars
或 TEncoding.GetString
将 value
转换为字符串。
可能看起来像这样:
var
Bytes: TBytes;
....
SetLength(Bytes, StrLen(value));
Move(value^, Pointer(Bytes)^, Length(Bytes));
str := TEncoding.UTF8.GetString(Bytes);
现在,对于将str
设置为cedlands@googlemail.com
的问题中的数据。如上所述,数据包含一个空终止符,当它被错误地解释为 UTF-16 时,它无法终止字符串。也就是说,文本 4CSA-7GFJ-YMW4-2VTF-II5Q-BNTA♥♦
来自缓冲区溢出。
我在将 UTF-8 编码字符串转换回 delphi 可用的内容时遇到问题。 该应用程序是用 XE8 编写的,正在 windows 和 OSX 上部署。该应用程序分别在 windows 和 OSX 上使用 LimeLM API dll 和 dylib 库。 在 windows 上一切正常,我遇到的问题是转换从 OSX 上的 dylib 库返回的字符串。我很欣赏所有进出 dylib 的字符串都需要采用 UTF-8 编码。 limeLM 函数 returns 一个 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 = '散汤滩杀豪汧浥楡潣m伴侣仓㜭万ⵊ佑㑗㈭喔ⵆ义势䈭嘶'#4
但 tmpStr 始终包含 '??????????c??????/'
如有任何帮助,我们将不胜感激。
value = '散汤湡獤杀潯汧浥楡潣m䌴䅓㜭䙇ⵊ䵙㑗㈭呖ⵆ䥉儵䈭呎́'#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)
编辑的字节数组 return,您会发现它包含一个空值。所以实际上该字符串在电子邮件地址之后以 null 结尾。
问题从这里开始:
value : PWideChar;
....
value := GetFeatureValue(FieldName, nil);
事实上GetFeatureValue
returns PAnsiChar
。有效载荷是 UTF-8 编码的,假设我对你的解释是正确的。
因此您需要进行以下更改:
- 将
GetFeatureValue
的 return 类型更改为PAnsiChar
。 - 将
value
的类型更改为PAnsiChar
。 - 使用
UnicodeFromLocaleChars
或TEncoding.GetString
将value
转换为字符串。
可能看起来像这样:
var
Bytes: TBytes;
....
SetLength(Bytes, StrLen(value));
Move(value^, Pointer(Bytes)^, Length(Bytes));
str := TEncoding.UTF8.GetString(Bytes);
现在,对于将str
设置为cedlands@googlemail.com
的问题中的数据。如上所述,数据包含一个空终止符,当它被错误地解释为 UTF-16 时,它无法终止字符串。也就是说,文本 4CSA-7GFJ-YMW4-2VTF-II5Q-BNTA♥♦
来自缓冲区溢出。