Delphi 7 并解码 UTF-8 base64

Delphi 7 and decode UTF-8 base64

在 Delphi 7 中,我有一个用 Base64 编码的宽字符串(我从 Web 服务收到的 WideString 结果):

PD94bWwgdmVyc2lvbj0iMS4wIj8+DQo8c3RyaW5nPtiq2LPYqjwvc3RyaW5nPg==

当我解码它时,结果不是 UTF-8:

<?xml version="1.0"?>
<string>طھط³طھ</string>

但是当我用base64decode.org解码时,结果是真的:

<?xml version="1.0"?>
<string>تست</string>

我已经将 EncdDecd 单元用于 DecodeString 函数。

您遇到的问题是您正在使用 DecodeString。在 Delphi 7 中,该函数将解码后的二进制数据视为 ANSI 编码。问题是您的文本是 UTF-8 编码的。

要继续使用 EncdDecd 单元,您有几个选择。您可以切换到 DecodeStream。例如,此代码将使用您的数据生成一个 UTF-8 编码的文本文件:

{$APPTYPE CONSOLE}

uses
  Classes,
  EncdDecd;

const
  Data = 'PD94bWwgdmVyc2lvbj0iMS4wIj8+DQo8c3RyaW5nPtiq2LPYqjwvc3RyaW5nPg==';

var
  Input: TStringStream;
  Output: TFileStream;

begin
  Input := TStringStream.Create(Data);
  try
    Output := TFileStream.Create('C:\desktop\out.txt', fmCreate);
    try
      DecodeStream(Input, Output);
    finally
      Output.Free;
    end;
  finally
    Input.Free;
  end;
end.

或者您可以继续 DecodeString,但随后立即将 UTF-8 文本解码为 WideString。像这样:

{$APPTYPE CONSOLE}

uses
  Classes,
  EncdDecd;

const
  Data = 'PD94bWwgdmVyc2lvbj0iMS4wIj8+DQo8c3RyaW5nPtiq2LPYqjwvc3RyaW5nPg==';

var
  Utf8: AnsiString;
  wstr: WideString;

begin
  Utf8 := DecodeString(Data);
  wstr := UTF8Decode(Utf8);
end.

如果文件的内容可以在您的应用程序的主流 ANSI 语言环境中表示,那么您可以将 WideString 转换为普通的 AnsiString.

var
  wstr: WideString;
  str: string; // alias to AnsiString
....
wstr := ... // as before
str := wstr;

但是,我真的不认为使用 ANSI 编码的文本会导致非常富有成果的编程生活。我鼓励您采用 Unicode 解决方案。

从解码数据的内容来看,是XML。通常交给 XML 解析器。大多数 XML 解析器将接受 UTF-8 编码数据,因此您很可能可以使用 DecodeStream 将 base64 解码为内存流,然后将该流传递给您的 XML 解析器。这样您就不需要将 UTF-8 解码为文本,并且可以让 XML 解析器处理这方面的问题。

作为 David Heffernan 精彩回答的附录,以及 Remy Lebeau 关于它如何在 Delphi 7 上被破坏的注释,我想添加一个功能,以帮助任何陷入 Delphi 7 的开发人员.

由于 UTF8Decode() 在 Delphi 7 中被破坏,我在 forum 中找到一个函数解决了我的问题:

function UTF8ToWideString(const S: AnsiString): WideString;
var
  BufSize: Integer;
begin
  Result := '';
  if Length(S) = 0 then Exit;
  BufSize := MultiByteToWideChar(CP_UTF8, 0, PAnsiChar(S), Length(S), nil, 0);
  SetLength(result, BufSize);
  MultiByteToWideChar(CP_UTF8, 0, PANsiChar(S), Length(S), PWideChar(Result), BufSize);
end;

所以现在,您可以使用 DecodeString,然后使用此函数将 UTF-8 文本解码为 WideString

begin
  Utf8 := DecodeString(Data);
  wstr := UTF8ToWideString(Utf8);
end.