【问题标题】:Delphi XE7- Convert memo to UTF8Delphi XE7 - 将备忘录转换为 UTF8
【发布时间】:2021-01-15 07:55:46
【问题描述】:

如何将 memo.text 转换为 UTF-8 并通过 TIdMessage 组件发送到我的电子邮件?我使用了这个功能,但是它不能正常工作...

function TForm1.EncodeAsUTF8(UnicodeStr: string): AnsiString;
var
  UTF8Str: UTF8String;
  i: Integer;
begin

  UTF8Str := UTF8String(UnicodeStr);

  SetLength(Result, Length(UTF8Str));

  for i := 1 to Length(UTF8Str) do
    Result[i] := AnsiChar(Ord(UTF8Str[i])); 

end;

【问题讨论】:

  • 使用TEncoding.UTF8.GetBytes()。您不会将 UTF8 存储在 AnsiString 中。
  • 非常感谢您的回复,但还是不行。我有一个备注字段,其中一个值是 ''Kontož'',当我将该字符串发送到我的电子邮件时,我会收到它作为 ''Konto??''。
  • @Pekkala 这部分是因为 RTL 不知道您的 AnsiString 是 UTF-8 编码的,所以当它被分配给其他字符串时会执行错误的转换,例如在您的电子邮件代码中。但是你为什么要使用 UTF-8 编码的 AnsiString 呢?为什么在准备发送电子邮件的原始字节时,您的电子邮件代码不采用正常的strings 并将转换处理为 UTF-8?
  • TEncoding.UTF8.GetBytes() 有效。什么不起作用是你接下来用它做什么。我们不知道。您谈论将字符串发送到电子邮件。我们对此一无所知。
  • 我还记得 Lazarus 标签,因为它与 Delphi XE7 不符。尽量准确地标记您的标签。

标签: delphi delphi-xe7


【解决方案1】:

您的函数没有让 RTL 知道 AnsiString 是 UTF-8 编码的。因此,当函数退出后将AnsiString 分配给其他字符串时,可能会发生数据丢失

如果您绝对需要返回 UTF-8 编码的AnsiString(我不推荐),那么您必须确保其元数据状态字符使用 UTF-8,例如:

function TForm1.EncodeAsUTF8(UnicodeStr: string): AnsiString;
var
  UTF8Str: UTF8String;
begin
  UTF8Str := UTF8String(UnicodeStr);
  SetString(Result, PAnsiChar(UTF8Str), Length(UTF8Str));
  SetCodePage(PRawByteString(@Result)^, CP_UTF8, False);
end;

或者:

function TForm1.EncodeAsUTF8(UnicodeStr: string): AnsiString;
begin
  PUTF8String(@Result)^ := UnicodeStr;
end;

但是,只返回 UTF8String 并让 RTL 为您处理 UTF-8 会简单得多,例如:

function TForm1.EncodeAsUTF8(UnicodeStr: string): UTF8String;
begin
  Result := UnicodeStr;
end;

或者,至少返回一个 UTF-8 编码的RawByteString,例如:

function TForm1.EncodeAsUTF8(UnicodeStr: string): RawByteString;
begin
  Result := UTF8String(UnicodeStr);
end;

更新:话虽如此,TIdMessage 是一个 Indy 组件,Indy 在正常的 String 值上运行。在 Unicode 版本的 Delphi(和 FPC)中,Indy 会在准备发送电子邮件时为您处理 UTF-8 编码。只需将TIdMessage.Body 设置为保存备忘录的普通Unicode 文本,并将TIdMessage.CharSet 设置为'utf-8',例如:

MailMessage.Body := Memo.Lines;
// or: MailMessage.Body.Text := Memo.Text;
MailMessage.CharSet := 'utf-8';

这就是你所需要的。您根本不必手动将备忘录文本编码为 UTF-8。

只有在 Delphi(和 FPC)的非 Unicode 版本中,使用 EncodeAsUTF8() 函数才有意义。仍然需要设置 TIdMessage.CharSet 属性,以便电子邮件标头声明 UTF-8,但 Indy 将按原样发送 AnsiString 字节而不重新编码它们,因此您将负责确保 AnsiString正在使用 UTF-8,例如:

function TForm1.EncodeAsUTF8(UnicodeStr: string): AnsiString;
begin
  Result := UTF8Encode(UnicodeStr);
end;

...

MailMessage.Body.Text := EncodeAsUTF8(Memo.Text);
MailMessage.CharSet := 'utf-8';

【讨论】:

    猜你喜欢
    • 2016-10-21
    • 1970-01-01
    • 2011-05-18
    • 1970-01-01
    • 1970-01-01
    • 2016-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多