使用单位LazUTF8时TIdURI.URLDecode的错误结果

问题描述 投票:0回答:2

使用Free Pascal 3.0.4,这个测试程序正确地写了ÄÖÜ

program FPCTest;

uses IdURI;

begin
  WriteLn(TIdURI.URLDecode('%C3%84%C3%96%C3%9C'));
  ReadLn;
end.

但是,如果使用单位LazUTF8(如here所述),它会写入???

program FPCTest;

uses IdURI, LazUTF8;

begin
  WriteLn(TIdURI.URLDecode('%C3%84%C3%96%C3%9C'));
  ReadLn;
end.

如何为使用LazUTF8的程序修复此解码错误?

http utf-8 indy lazarus freepascal
2个回答
2
投票

String类型是AnsiString 1的别名时,Indy的大部分功能都会暴露额外的参数/属性,以便用户控制在执行AnsiString转换的操作中传递AnsiString<->byte值时使用的ANSI编码。

1:2009年之前的德尔福,以及不使用{$ModeSwitch UnicodeStrings}{$Mode DelphiUnicode}的FreePascal / Lazarus(FYI,Indy 11将使用它们!)。

在大多数情况下,Indy的默认字节编码是ASCII(因为Indy实现的许多Internet协议最初只支持ASCII - 个别Indy组件根据协议将其自身升级为UTF),尽管有些东西使用操作系统默认代码页/字符集代替。

通过在GIdDefaultTextEncoding单元中设置全局IdGlobal变量,可以在运行时更改Indy的默认字节编码,例如:

GIdDefaultTextEncoding := encUTF8;

但是,在这种特殊情况下,TIdURI.URLEncode()不使用GIdDefaultTextEncoding,但它确实有一个可选的ADestEncoding参数,可用于为返回的AnsiString指定特定的字节编码(除了可选的AByteEncoding参数以指定字节编码)解析url八位字节 - 默认为UTF-8),例如:

TIdURI.URLDecode('%C3%84%C3%96%C3%9C'
  {$IFNDEF FPC_UNICODESTRINGS}, IndyTextEncoding_UTF8, IndyTextEncoding_UTF8{$ENDIF}
)

上面将解析url编码的八位字节为UTF-8,然后按原样在UTF-8编码的AnsiString中返回该数据。

如果没有为ADestEncoding指定输出编码,则URLDecode()默认为操作系统默认值。如果您希望它使用GIdDefaultTextEncoding,请在IndyTextEncoding_Default参数中指定ADestEncoding

TIdURI.URLDecode('%C3%84%C3%96%C3%9C'
  {$IFNDEF FPC_UNICODESTRINGS}, IndyTextEncoding_UTF8, IndyTextEncoding_Default{$ENDIF}
)

另一个选择是使用IndyTextEncoding(CodePage)函数为ADestEncoding,传递它FreePascal的DefaultSystemCodePage变量,LazUtils包设置为CP_UTF8 2:

TIdURI.URLDecode('%C3%84%C3%96%C3%9C'
  {$IFNDEF FPC_UNICODESTRINGS}, IndyTextEncoding_UTF8, IndyTextEncoding(DefaultSystemCodePage){$ENDIF}
)

2:我在Indy的问题跟踪器中有opened a ticket,以便在编译FreePascal / Lazarus时添加对DefaultSystemCodePage的支持。


0
投票

通过TIdURI.URLDecode行中的这一变化,可以使用386ff LazUTF8:

  {$IFDEF FPC}
  Result := string(AByteEncoding.GetString(LBytes));
  {$ELSE}
  {$IFDEF STRING_IS_ANSI}
  EnsureEncoding(ADestEncoding, encOSDefault);
  CheckByteEncoding(LBytes, AByteEncoding, ADestEncoding);
  SetString(Result, PAnsiChar(LBytes), Length(LBytes));
  {$ELSE}
  Result := AByteEncoding.GetString(LBytes);
  {$ENDIF}
  {$ENDIF}

笔记

此更改假定始终使用LazUTF8单元,并且每次使用新版本时都需要应用Indy源代码更改。

此外,我发现无法使用和不使用LazUTF8的方式修复TIdURI.URLDecode。

© www.soinside.com 2019 - 2024. All rights reserved.